Home | History | Annotate | Download | only in login
      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 #include "chrome/browser/chromeos/login/enterprise_enrollment_screen.h"
      6 
      7 #include "base/logging.h"
      8 #include "chrome/browser/browser_process.h"
      9 #include "chrome/browser/chromeos/cros/cros_library.h"
     10 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
     11 #include "chrome/browser/chromeos/login/screen_observer.h"
     12 #include "chrome/browser/policy/browser_policy_connector.h"
     13 #include "chrome/common/net/gaia/gaia_constants.h"
     14 
     15 namespace chromeos {
     16 
     17 // Retry for InstallAttrs initialization every 500ms.
     18 const int kLockRetryIntervalMs = 500;
     19 
     20 EnterpriseEnrollmentScreen::EnterpriseEnrollmentScreen(
     21     WizardScreenDelegate* delegate)
     22     : ViewScreen<EnterpriseEnrollmentView>(delegate),
     23       ALLOW_THIS_IN_INITIALIZER_LIST(runnable_method_factory_(this)) {
     24   // Init the TPM if it has not been done until now (in debug build we might
     25   // have not done that yet).
     26   chromeos::CryptohomeLibrary* cryptohome =
     27       chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
     28   if (cryptohome) {
     29     if (cryptohome->TpmIsEnabled() &&
     30         !cryptohome->TpmIsBeingOwned() &&
     31         !cryptohome->TpmIsOwned()) {
     32       cryptohome->TpmCanAttemptOwnership();
     33     }
     34   }
     35 }
     36 
     37 EnterpriseEnrollmentScreen::~EnterpriseEnrollmentScreen() {}
     38 
     39 void EnterpriseEnrollmentScreen::Authenticate(const std::string& user,
     40                                               const std::string& password,
     41                                               const std::string& captcha,
     42                                               const std::string& access_code) {
     43   captcha_token_.clear();
     44   user_ = user;
     45   auth_fetcher_.reset(
     46       new GaiaAuthFetcher(this, GaiaConstants::kChromeSource,
     47                           g_browser_process->system_request_context()));
     48 
     49   if (access_code.empty()) {
     50     auth_fetcher_->StartClientLogin(user, password,
     51                                     GaiaConstants::kDeviceManagementService,
     52                                     captcha_token_, captcha,
     53                                     GaiaAuthFetcher::HostedAccountsAllowed);
     54   } else {
     55     auth_fetcher_->StartClientLogin(user, access_code,
     56                                     GaiaConstants::kDeviceManagementService,
     57                                     std::string(), std::string(),
     58                                     GaiaAuthFetcher::HostedAccountsAllowed);
     59   }
     60 }
     61 
     62 void EnterpriseEnrollmentScreen::CancelEnrollment() {
     63   auth_fetcher_.reset();
     64   registrar_.reset();
     65   g_browser_process->browser_policy_connector()->StopAutoRetry();
     66   ScreenObserver* observer = delegate()->GetObserver(this);
     67   observer->OnExit(ScreenObserver::ENTERPRISE_ENROLLMENT_CANCELLED);
     68 }
     69 
     70 void EnterpriseEnrollmentScreen::CloseConfirmation() {
     71   auth_fetcher_.reset();
     72   ScreenObserver* observer = delegate()->GetObserver(this);
     73   observer->OnExit(ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED);
     74 }
     75 
     76 bool EnterpriseEnrollmentScreen::GetInitialUser(std::string* user) {
     77   chromeos::CryptohomeLibrary* cryptohome =
     78       chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
     79   if (cryptohome &&
     80       cryptohome->InstallAttributesIsReady() &&
     81       !cryptohome->InstallAttributesIsFirstInstall()) {
     82     std::string value;
     83     if (cryptohome->InstallAttributesGet("enterprise.owned", &value) &&
     84         value == "true") {
     85       if (cryptohome->InstallAttributesGet("enterprise.user", &value)) {
     86         // If we landed in the enrollment dialogue with a locked InstallAttrs
     87         // this means we might only want to reenroll with the DMServer so lock
     88         // the username to what has been stored in the InstallAttrs already.
     89         *user = value;
     90         if (view())
     91           view()->set_editable_user(false);
     92         return true;
     93       }
     94     }
     95     LOG(ERROR) << "Enrollment will not finish because the InstallAttrs has "
     96                << "been locked already but does not contain valid data.";
     97   }
     98   return false;
     99 }
    100 
    101 void EnterpriseEnrollmentScreen::OnClientLoginSuccess(
    102     const ClientLoginResult& result) {
    103   auth_fetcher_->StartIssueAuthToken(
    104           result.sid, result.lsid, GaiaConstants::kDeviceManagementService);
    105 }
    106 
    107 void EnterpriseEnrollmentScreen::OnClientLoginFailure(
    108     const GoogleServiceAuthError& error) {
    109   HandleAuthError(error);
    110 }
    111 
    112 void EnterpriseEnrollmentScreen::OnIssueAuthTokenSuccess(
    113     const std::string& service,
    114     const std::string& auth_token) {
    115   if (service != GaiaConstants::kDeviceManagementService) {
    116     NOTREACHED() << service;
    117     return;
    118   }
    119 
    120   scoped_ptr<GaiaAuthFetcher> auth_fetcher(auth_fetcher_.release());
    121 
    122   policy::BrowserPolicyConnector* connector =
    123       g_browser_process->browser_policy_connector();
    124   if (!connector->cloud_policy_subsystem()) {
    125     NOTREACHED() << "Cloud policy subsystem not initialized.";
    126     if (view())
    127       view()->ShowFatalEnrollmentError();
    128     return;
    129   }
    130 
    131   registrar_.reset(new policy::CloudPolicySubsystem::ObserverRegistrar(
    132       connector->cloud_policy_subsystem(), this));
    133 
    134   // Push the credentials to the policy infrastructure. It'll start enrollment
    135   // and notify us of progress through CloudPolicySubsystem::Observer.
    136   connector->SetCredentials(user_, auth_token);
    137 }
    138 
    139 void EnterpriseEnrollmentScreen::OnIssueAuthTokenFailure(
    140     const std::string& service,
    141     const GoogleServiceAuthError& error) {
    142   if (service != GaiaConstants::kDeviceManagementService) {
    143     NOTREACHED() << service;
    144     return;
    145   }
    146 
    147   HandleAuthError(error);
    148 }
    149 
    150 void EnterpriseEnrollmentScreen::OnPolicyStateChanged(
    151     policy::CloudPolicySubsystem::PolicySubsystemState state,
    152     policy::CloudPolicySubsystem::ErrorDetails error_details) {
    153 
    154   if (view()) {
    155     switch (state) {
    156       case policy::CloudPolicySubsystem::UNENROLLED:
    157         // Still working...
    158         return;
    159       case policy::CloudPolicySubsystem::BAD_GAIA_TOKEN:
    160       case policy::CloudPolicySubsystem::LOCAL_ERROR:
    161         view()->ShowFatalEnrollmentError();
    162         break;
    163       case policy::CloudPolicySubsystem::UNMANAGED:
    164         view()->ShowAccountError();
    165         break;
    166       case policy::CloudPolicySubsystem::NETWORK_ERROR:
    167         view()->ShowNetworkEnrollmentError();
    168         break;
    169       case policy::CloudPolicySubsystem::TOKEN_FETCHED:
    170         WriteInstallAttributesData();
    171         return;
    172       case policy::CloudPolicySubsystem::SUCCESS:
    173         // Success!
    174         registrar_.reset();
    175         view()->ShowConfirmationScreen();
    176         return;
    177     }
    178 
    179     // We have an error.
    180     LOG(WARNING) << "Policy subsystem error during enrollment: " << state
    181                  << " details: " << error_details;
    182   }
    183 
    184   // Stop the policy infrastructure.
    185   registrar_.reset();
    186   g_browser_process->browser_policy_connector()->StopAutoRetry();
    187 }
    188 
    189 EnterpriseEnrollmentView* EnterpriseEnrollmentScreen::AllocateView() {
    190   return new EnterpriseEnrollmentView(this);
    191 }
    192 
    193 void EnterpriseEnrollmentScreen::HandleAuthError(
    194     const GoogleServiceAuthError& error) {
    195   scoped_ptr<GaiaAuthFetcher> scoped_killer(auth_fetcher_.release());
    196 
    197   if (!view())
    198     return;
    199 
    200   switch (error.state()) {
    201     case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
    202     case GoogleServiceAuthError::CONNECTION_FAILED:
    203     case GoogleServiceAuthError::CAPTCHA_REQUIRED:
    204     case GoogleServiceAuthError::TWO_FACTOR:
    205       view()->ShowAuthError(error);
    206       return;
    207     case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
    208     case GoogleServiceAuthError::ACCOUNT_DELETED:
    209     case GoogleServiceAuthError::ACCOUNT_DISABLED:
    210     case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
    211       view()->ShowAccountError();
    212       return;
    213     case GoogleServiceAuthError::NONE:
    214     case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
    215       NOTREACHED() << error.state();
    216       // fall through.
    217     case GoogleServiceAuthError::REQUEST_CANCELED:
    218       LOG(ERROR) << "Unexpected GAIA auth error: " << error.state();
    219       view()->ShowFatalAuthError();
    220       return;
    221   }
    222 
    223   NOTREACHED() << error.state();
    224 }
    225 
    226 void EnterpriseEnrollmentScreen::WriteInstallAttributesData() {
    227   // Since this method is also called directly.
    228   runnable_method_factory_.RevokeAll();
    229 
    230   if (!view())
    231     return;
    232 
    233   switch (g_browser_process->browser_policy_connector()->LockDevice(user_)) {
    234     case policy::EnterpriseInstallAttributes::LOCK_SUCCESS: {
    235       // Proceed with policy fetch.
    236       policy::BrowserPolicyConnector* connector =
    237           g_browser_process->browser_policy_connector();
    238       connector->FetchPolicy();
    239       return;
    240     }
    241     case policy::EnterpriseInstallAttributes::LOCK_NOT_READY: {
    242       // InstallAttributes not ready yet, retry later.
    243       LOG(WARNING) << "Install Attributes not ready yet will retry in "
    244                    << kLockRetryIntervalMs << "ms.";
    245       MessageLoop::current()->PostDelayedTask(
    246           FROM_HERE,
    247           runnable_method_factory_.NewRunnableMethod(
    248               &EnterpriseEnrollmentScreen::WriteInstallAttributesData),
    249           kLockRetryIntervalMs);
    250       return;
    251     }
    252     case policy::EnterpriseInstallAttributes::LOCK_BACKEND_ERROR: {
    253       view()->ShowFatalEnrollmentError();
    254       return;
    255     }
    256     case policy::EnterpriseInstallAttributes::LOCK_WRONG_USER: {
    257       LOG(ERROR) << "Enrollment can not proceed because the InstallAttrs "
    258                  << "has been locked already!";
    259       view()->ShowFatalEnrollmentError();
    260       return;
    261     }
    262   }
    263 
    264   NOTREACHED();
    265 }
    266 
    267 }  // namespace chromeos
    268