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