• 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 #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 
EnterpriseEnrollmentScreen(WizardScreenDelegate * delegate)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 
~EnterpriseEnrollmentScreen()37 EnterpriseEnrollmentScreen::~EnterpriseEnrollmentScreen() {}
38 
Authenticate(const std::string & user,const std::string & password,const std::string & captcha,const std::string & access_code)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 
CancelEnrollment()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 
CloseConfirmation()70 void EnterpriseEnrollmentScreen::CloseConfirmation() {
71   auth_fetcher_.reset();
72   ScreenObserver* observer = delegate()->GetObserver(this);
73   observer->OnExit(ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED);
74 }
75 
GetInitialUser(std::string * user)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 
OnClientLoginSuccess(const ClientLoginResult & result)101 void EnterpriseEnrollmentScreen::OnClientLoginSuccess(
102     const ClientLoginResult& result) {
103   auth_fetcher_->StartIssueAuthToken(
104           result.sid, result.lsid, GaiaConstants::kDeviceManagementService);
105 }
106 
OnClientLoginFailure(const GoogleServiceAuthError & error)107 void EnterpriseEnrollmentScreen::OnClientLoginFailure(
108     const GoogleServiceAuthError& error) {
109   HandleAuthError(error);
110 }
111 
OnIssueAuthTokenSuccess(const std::string & service,const std::string & auth_token)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 
OnIssueAuthTokenFailure(const std::string & service,const GoogleServiceAuthError & error)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 
OnPolicyStateChanged(policy::CloudPolicySubsystem::PolicySubsystemState state,policy::CloudPolicySubsystem::ErrorDetails error_details)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 
AllocateView()189 EnterpriseEnrollmentView* EnterpriseEnrollmentScreen::AllocateView() {
190   return new EnterpriseEnrollmentView(this);
191 }
192 
HandleAuthError(const GoogleServiceAuthError & error)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 
WriteInstallAttributesData()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