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 15namespace chromeos { 16 17// Retry for InstallAttrs initialization every 500ms. 18const int kLockRetryIntervalMs = 500; 19 20EnterpriseEnrollmentScreen::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 37EnterpriseEnrollmentScreen::~EnterpriseEnrollmentScreen() {} 38 39void 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 62void 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 70void EnterpriseEnrollmentScreen::CloseConfirmation() { 71 auth_fetcher_.reset(); 72 ScreenObserver* observer = delegate()->GetObserver(this); 73 observer->OnExit(ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED); 74} 75 76bool 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 101void EnterpriseEnrollmentScreen::OnClientLoginSuccess( 102 const ClientLoginResult& result) { 103 auth_fetcher_->StartIssueAuthToken( 104 result.sid, result.lsid, GaiaConstants::kDeviceManagementService); 105} 106 107void EnterpriseEnrollmentScreen::OnClientLoginFailure( 108 const GoogleServiceAuthError& error) { 109 HandleAuthError(error); 110} 111 112void 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 139void 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 150void 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 189EnterpriseEnrollmentView* EnterpriseEnrollmentScreen::AllocateView() { 190 return new EnterpriseEnrollmentView(this); 191} 192 193void 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 226void 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