Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / chromeos / policy / enrollment_handler_chromeos.cc
blobcf9c94b27dd4a3e86d5783f62b1984e31a378749
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/chromeos/policy/enrollment_handler_chromeos.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
13 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
14 #include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h"
15 #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
16 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
17 #include "chrome/browser/chromeos/policy/server_backed_state_keys_broker.h"
18 #include "chrome/browser/chromeos/profiles/profile_helper.h"
19 #include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
20 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chromeos/chromeos_switches.h"
23 #include "google_apis/gaia/gaia_urls.h"
24 #include "net/http/http_status_code.h"
26 namespace em = enterprise_management;
28 namespace policy {
30 namespace {
32 // Retry for InstallAttrs initialization every 500ms.
33 const int kLockRetryIntervalMs = 500;
34 // Maximum time to retry InstallAttrs initialization before we give up.
35 const int kLockRetryTimeoutMs = 10 * 60 * 1000; // 10 minutes.
37 // Testing token used when the enrollment-skip-robot-auth is set to skip talking
38 // to GAIA for an actual token. This is needed to be able to run against the
39 // testing DMServer implementations.
40 const char kTestingRobotToken[] = "test-token";
42 em::DeviceRegisterRequest::Flavor EnrollmentModeToRegistrationFlavor(
43 policy::EnrollmentConfig::Mode mode) {
44 switch (mode) {
45 case policy::EnrollmentConfig::MODE_NONE:
46 break;
47 case policy::EnrollmentConfig::MODE_MANUAL:
48 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_MANUAL;
49 case policy::EnrollmentConfig::MODE_MANUAL_REENROLLMENT:
50 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_MANUAL_RENEW;
51 case policy::EnrollmentConfig::MODE_LOCAL_FORCED:
52 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_LOCAL_FORCED;
53 case policy::EnrollmentConfig::MODE_LOCAL_ADVERTISED:
54 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_LOCAL_ADVERTISED;
55 case policy::EnrollmentConfig::MODE_SERVER_FORCED:
56 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_SERVER_FORCED;
57 case policy::EnrollmentConfig::MODE_SERVER_ADVERTISED:
58 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_SERVER_ADVERTISED;
59 case policy::EnrollmentConfig::MODE_RECOVERY:
60 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_RECOVERY;
63 NOTREACHED() << "Bad enrollment mode: " << mode;
64 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_MANUAL;
67 } // namespace
69 EnrollmentHandlerChromeOS::EnrollmentHandlerChromeOS(
70 DeviceCloudPolicyStoreChromeOS* store,
71 EnterpriseInstallAttributes* install_attributes,
72 ServerBackedStateKeysBroker* state_keys_broker,
73 chromeos::OwnerSettingsServiceChromeOS* owner_settings_service,
74 scoped_ptr<CloudPolicyClient> client,
75 scoped_refptr<base::SequencedTaskRunner> background_task_runner,
76 const EnrollmentConfig& enrollment_config,
77 const std::string& auth_token,
78 const std::string& client_id,
79 const std::string& requisition,
80 const AllowedDeviceModes& allowed_device_modes,
81 ManagementMode management_mode,
82 const EnrollmentCallback& completion_callback)
83 : store_(store),
84 install_attributes_(install_attributes),
85 state_keys_broker_(state_keys_broker),
86 owner_settings_service_(owner_settings_service),
87 client_(client.Pass()),
88 background_task_runner_(background_task_runner),
89 enrollment_config_(enrollment_config),
90 auth_token_(auth_token),
91 client_id_(client_id),
92 requisition_(requisition),
93 allowed_device_modes_(allowed_device_modes),
94 management_mode_(management_mode),
95 completion_callback_(completion_callback),
96 device_mode_(DEVICE_MODE_NOT_SET),
97 enrollment_step_(STEP_PENDING),
98 lockbox_init_duration_(0),
99 weak_ptr_factory_(this) {
100 CHECK(!client_->is_registered());
101 CHECK_EQ(DM_STATUS_SUCCESS, client_->status());
102 CHECK(management_mode_ == MANAGEMENT_MODE_ENTERPRISE_MANAGED ||
103 management_mode_ == MANAGEMENT_MODE_CONSUMER_MANAGED);
104 store_->AddObserver(this);
105 client_->AddObserver(this);
106 client_->AddPolicyTypeToFetch(dm_protocol::kChromeDevicePolicyType,
107 std::string());
110 EnrollmentHandlerChromeOS::~EnrollmentHandlerChromeOS() {
111 Stop();
112 store_->RemoveObserver(this);
115 void EnrollmentHandlerChromeOS::StartEnrollment() {
116 CHECK_EQ(STEP_PENDING, enrollment_step_);
117 enrollment_step_ = STEP_STATE_KEYS;
118 state_keys_broker_->RequestStateKeys(
119 base::Bind(&EnrollmentHandlerChromeOS::HandleStateKeysResult,
120 weak_ptr_factory_.GetWeakPtr()));
123 scoped_ptr<CloudPolicyClient> EnrollmentHandlerChromeOS::ReleaseClient() {
124 Stop();
125 return client_.Pass();
128 void EnrollmentHandlerChromeOS::OnPolicyFetched(CloudPolicyClient* client) {
129 DCHECK_EQ(client_.get(), client);
130 CHECK_EQ(STEP_POLICY_FETCH, enrollment_step_);
132 enrollment_step_ = STEP_VALIDATION;
134 // Validate the policy.
135 const em::PolicyFetchResponse* policy = client_->GetPolicyFor(
136 dm_protocol::kChromeDevicePolicyType, std::string());
137 if (!policy) {
138 ReportResult(EnrollmentStatus::ForFetchError(
139 DM_STATUS_RESPONSE_DECODING_ERROR));
140 return;
143 scoped_ptr<DeviceCloudPolicyValidator> validator(
144 DeviceCloudPolicyValidator::Create(
145 scoped_ptr<em::PolicyFetchResponse>(
146 new em::PolicyFetchResponse(*policy)),
147 background_task_runner_));
149 validator->ValidateTimestamp(base::Time(), base::Time::NowFromSystemTime(),
150 CloudPolicyValidatorBase::TIMESTAMP_REQUIRED);
152 // If this is re-enrollment, make sure that the new policy matches the
153 // previously-enrolled domain.
154 std::string domain;
155 if (install_attributes_->IsEnterpriseDevice()) {
156 domain = install_attributes_->GetDomain();
157 validator->ValidateDomain(domain);
159 validator->ValidateDMToken(client->dm_token(),
160 CloudPolicyValidatorBase::DM_TOKEN_REQUIRED);
161 validator->ValidatePolicyType(dm_protocol::kChromeDevicePolicyType);
162 validator->ValidatePayload();
163 if (management_mode_ == MANAGEMENT_MODE_CONSUMER_MANAGED) {
164 // For consumer-managed devices, although we don't store the policy, we
165 // still need to verify its integrity since we use the request token in it.
166 // The consumer device management server does not have the verification
167 // key, and we need to skip checking on that by passing an empty key to
168 // ValidateInitialKey(). ValidateInitialKey() still checks that the policy
169 // data is correctly signed by the new public key when the verification key
170 // is empty.
171 validator->ValidateInitialKey(std::string(), std::string());
172 } else {
173 // If |domain| is empty here, the policy validation code will just use the
174 // domain from the username field in the policy itself to do key validation.
175 // TODO(mnissler): Plumb the enrolling user's username into this object so
176 // we can validate the username on the resulting policy, and use the domain
177 // from that username to validate the key below (http://crbug.com/343074).
178 validator->ValidateInitialKey(GetPolicyVerificationKey(), domain);
180 validator.release()->StartValidation(
181 base::Bind(&EnrollmentHandlerChromeOS::HandlePolicyValidationResult,
182 weak_ptr_factory_.GetWeakPtr()));
185 void EnrollmentHandlerChromeOS::OnRegistrationStateChanged(
186 CloudPolicyClient* client) {
187 DCHECK_EQ(client_.get(), client);
189 if (enrollment_step_ == STEP_REGISTRATION && client_->is_registered()) {
190 enrollment_step_ = STEP_POLICY_FETCH,
191 device_mode_ = client_->device_mode();
192 if (device_mode_ == DEVICE_MODE_NOT_SET)
193 device_mode_ = DEVICE_MODE_ENTERPRISE;
194 if (!allowed_device_modes_.test(device_mode_)) {
195 LOG(ERROR) << "Bad device mode " << device_mode_;
196 ReportResult(EnrollmentStatus::ForStatus(
197 EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE));
198 return;
200 client_->FetchPolicy();
201 } else {
202 LOG(FATAL) << "Registration state changed to " << client_->is_registered()
203 << " in step " << enrollment_step_ << ".";
207 void EnrollmentHandlerChromeOS::OnClientError(CloudPolicyClient* client) {
208 DCHECK_EQ(client_.get(), client);
210 if (enrollment_step_ == STEP_ROBOT_AUTH_FETCH) {
211 LOG(ERROR) << "API authentication code fetch failed: "
212 << client_->status();
213 ReportResult(EnrollmentStatus::ForRobotAuthFetchError(client_->status()));
214 } else if (enrollment_step_ < STEP_POLICY_FETCH) {
215 ReportResult(EnrollmentStatus::ForRegistrationError(client_->status()));
216 } else {
217 ReportResult(EnrollmentStatus::ForFetchError(client_->status()));
221 void EnrollmentHandlerChromeOS::OnStoreLoaded(CloudPolicyStore* store) {
222 DCHECK_EQ(store_, store);
224 if (enrollment_step_ == STEP_LOADING_STORE) {
225 // If the |store_| wasn't initialized when StartEnrollment() was called,
226 // then StartRegistration() bails silently. This gets registration rolling
227 // again after the store finishes loading.
228 StartRegistration();
229 } else if (enrollment_step_ == STEP_STORE_POLICY) {
230 ReportResult(EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_SUCCESS));
234 void EnrollmentHandlerChromeOS::OnStoreError(CloudPolicyStore* store) {
235 DCHECK_EQ(store_, store);
236 if (enrollment_step_ == STEP_STORE_TOKEN_AND_ID) {
237 // Calling OwnerSettingsServiceChromeOS::SetManagementSettings()
238 // on a non- enterprise-managed device will fail as
239 // DeviceCloudPolicyStore listens to all changes on device
240 // settings, and it calls OnStoreError() when the device is not
241 // enterprise-managed.
242 return;
244 ReportResult(EnrollmentStatus::ForStoreError(store_->status(),
245 store_->validation_status()));
248 void EnrollmentHandlerChromeOS::HandleStateKeysResult(
249 const std::vector<std::string>& state_keys) {
250 CHECK_EQ(STEP_STATE_KEYS, enrollment_step_);
252 // Make sure state keys are available if forced re-enrollment is on.
253 if (chromeos::AutoEnrollmentController::GetMode() ==
254 chromeos::AutoEnrollmentController::MODE_FORCED_RE_ENROLLMENT) {
255 client_->SetStateKeysToUpload(state_keys);
256 current_state_key_ = state_keys_broker_->current_state_key();
257 if (state_keys.empty() || current_state_key_.empty()) {
258 ReportResult(
259 EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_NO_STATE_KEYS));
260 return;
264 enrollment_step_ = STEP_LOADING_STORE;
265 StartRegistration();
268 void EnrollmentHandlerChromeOS::StartRegistration() {
269 CHECK_EQ(STEP_LOADING_STORE, enrollment_step_);
270 if (store_->is_initialized()) {
271 enrollment_step_ = STEP_REGISTRATION;
272 client_->Register(
273 em::DeviceRegisterRequest::DEVICE,
274 EnrollmentModeToRegistrationFlavor(enrollment_config_.mode),
275 auth_token_, client_id_, requisition_, current_state_key_);
276 } else {
277 // Do nothing. StartRegistration() will be called again from OnStoreLoaded()
278 // after the CloudPolicyStore has initialized.
282 void EnrollmentHandlerChromeOS::HandlePolicyValidationResult(
283 DeviceCloudPolicyValidator* validator) {
284 CHECK_EQ(STEP_VALIDATION, enrollment_step_);
285 if (validator->success()) {
286 policy_ = validator->policy().Pass();
287 username_ = validator->policy_data()->username();
288 device_id_ = validator->policy_data()->device_id();
289 request_token_ = validator->policy_data()->request_token();
291 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
292 chromeos::switches::kEnterpriseEnrollmentSkipRobotAuth)) {
293 // For test purposes we allow enrollment to succeed without proper robot
294 // account and use the provided value as a token.
295 refresh_token_ = kTestingRobotToken;
296 enrollment_step_ = STEP_LOCK_DEVICE;
297 StartLockDevice();
298 return;
301 enrollment_step_ = STEP_ROBOT_AUTH_FETCH;
302 client_->FetchRobotAuthCodes(auth_token_);
303 } else {
304 ReportResult(EnrollmentStatus::ForValidationError(validator->status()));
308 void EnrollmentHandlerChromeOS::OnRobotAuthCodesFetched(
309 CloudPolicyClient* client) {
310 DCHECK_EQ(client_.get(), client);
311 CHECK_EQ(STEP_ROBOT_AUTH_FETCH, enrollment_step_);
313 enrollment_step_ = STEP_ROBOT_AUTH_REFRESH;
315 gaia::OAuthClientInfo client_info;
316 client_info.client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
317 client_info.client_secret =
318 GaiaUrls::GetInstance()->oauth2_chrome_client_secret();
319 client_info.redirect_uri = "oob";
321 // Use the system request context to avoid sending user cookies.
322 gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(
323 g_browser_process->system_request_context()));
324 gaia_oauth_client_->GetTokensFromAuthCode(client_info,
325 client->robot_api_auth_code(),
326 0 /* max_retries */,
327 this);
330 // GaiaOAuthClient::Delegate callback for OAuth2 refresh token fetched.
331 void EnrollmentHandlerChromeOS::OnGetTokensResponse(
332 const std::string& refresh_token,
333 const std::string& access_token,
334 int expires_in_seconds) {
335 CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_);
337 refresh_token_ = refresh_token;
339 enrollment_step_ = STEP_LOCK_DEVICE;
340 StartLockDevice();
343 // GaiaOAuthClient::Delegate
344 void EnrollmentHandlerChromeOS::OnRefreshTokenResponse(
345 const std::string& access_token,
346 int expires_in_seconds) {
347 // We never use the code that should trigger this callback.
348 LOG(FATAL) << "Unexpected callback invoked.";
351 // GaiaOAuthClient::Delegate OAuth2 error when fetching refresh token request.
352 void EnrollmentHandlerChromeOS::OnOAuthError() {
353 CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_);
354 // OnOAuthError is only called if the request is bad (malformed) or the
355 // response is bad (empty access token returned).
356 LOG(ERROR) << "OAuth protocol error while fetching API refresh token.";
357 ReportResult(
358 EnrollmentStatus::ForRobotRefreshFetchError(net::HTTP_BAD_REQUEST));
361 // GaiaOAuthClient::Delegate network error when fetching refresh token.
362 void EnrollmentHandlerChromeOS::OnNetworkError(int response_code) {
363 CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_);
364 LOG(ERROR) << "Network error while fetching API refresh token: "
365 << response_code;
366 ReportResult(
367 EnrollmentStatus::ForRobotRefreshFetchError(response_code));
370 void EnrollmentHandlerChromeOS::StartLockDevice() {
371 CHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_);
372 // Since this method is also called directly.
373 weak_ptr_factory_.InvalidateWeakPtrs();
375 if (management_mode_ == MANAGEMENT_MODE_CONSUMER_MANAGED) {
376 CHECK(owner_settings_service_);
378 // Consumer device enrollment doesn't use install attributes. Instead,
379 // we put the information in the owners settings.
380 enrollment_step_ = STEP_STORE_TOKEN_AND_ID;
381 chromeos::OwnerSettingsServiceChromeOS::ManagementSettings settings;
382 settings.management_mode = management_mode_;
383 settings.request_token = request_token_;
384 settings.device_id = device_id_;
385 owner_settings_service_->SetManagementSettings(
386 settings,
387 base::Bind(&EnrollmentHandlerChromeOS::HandleSetManagementSettingsDone,
388 weak_ptr_factory_.GetWeakPtr()));
389 } else {
390 install_attributes_->LockDevice(
391 username_, device_mode_, device_id_,
392 base::Bind(&EnrollmentHandlerChromeOS::HandleLockDeviceResult,
393 weak_ptr_factory_.GetWeakPtr()));
397 void EnrollmentHandlerChromeOS::HandleSetManagementSettingsDone(bool success) {
398 CHECK_EQ(STEP_STORE_TOKEN_AND_ID, enrollment_step_);
399 if (!success) {
400 ReportResult(EnrollmentStatus::ForStatus(
401 EnrollmentStatus::STATUS_STORE_TOKEN_AND_ID_FAILED));
402 return;
405 StartStoreRobotAuth();
408 void EnrollmentHandlerChromeOS::HandleLockDeviceResult(
409 EnterpriseInstallAttributes::LockResult lock_result) {
410 CHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_);
411 switch (lock_result) {
412 case EnterpriseInstallAttributes::LOCK_SUCCESS:
413 StartStoreRobotAuth();
414 break;
415 case EnterpriseInstallAttributes::LOCK_NOT_READY:
416 // We wait up to |kLockRetryTimeoutMs| milliseconds and if it hasn't
417 // succeeded by then show an error to the user and stop the enrollment.
418 if (lockbox_init_duration_ < kLockRetryTimeoutMs) {
419 // InstallAttributes not ready yet, retry later.
420 LOG(WARNING) << "Install Attributes not ready yet will retry in "
421 << kLockRetryIntervalMs << "ms.";
422 base::MessageLoop::current()->PostDelayedTask(
423 FROM_HERE,
424 base::Bind(&EnrollmentHandlerChromeOS::StartLockDevice,
425 weak_ptr_factory_.GetWeakPtr()),
426 base::TimeDelta::FromMilliseconds(kLockRetryIntervalMs));
427 lockbox_init_duration_ += kLockRetryIntervalMs;
428 } else {
429 HandleLockDeviceResult(EnterpriseInstallAttributes::LOCK_TIMEOUT);
431 break;
432 case EnterpriseInstallAttributes::LOCK_TIMEOUT:
433 case EnterpriseInstallAttributes::LOCK_BACKEND_INVALID:
434 case EnterpriseInstallAttributes::LOCK_ALREADY_LOCKED:
435 case EnterpriseInstallAttributes::LOCK_SET_ERROR:
436 case EnterpriseInstallAttributes::LOCK_FINALIZE_ERROR:
437 case EnterpriseInstallAttributes::LOCK_READBACK_ERROR:
438 case EnterpriseInstallAttributes::LOCK_WRONG_DOMAIN:
439 ReportResult(EnrollmentStatus::ForLockError(lock_result));
440 break;
444 void EnrollmentHandlerChromeOS::StartStoreRobotAuth() {
445 // Get the token service so we can store our robot refresh token.
446 enrollment_step_ = STEP_STORE_ROBOT_AUTH;
447 chromeos::DeviceOAuth2TokenServiceFactory::Get()->SetAndSaveRefreshToken(
448 refresh_token_,
449 base::Bind(&EnrollmentHandlerChromeOS::HandleStoreRobotAuthTokenResult,
450 weak_ptr_factory_.GetWeakPtr()));
453 void EnrollmentHandlerChromeOS::HandleStoreRobotAuthTokenResult(bool result) {
454 CHECK_EQ(STEP_STORE_ROBOT_AUTH, enrollment_step_);
456 if (!result) {
457 LOG(ERROR) << "Failed to store API refresh token.";
458 ReportResult(EnrollmentStatus::ForStatus(
459 EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED));
460 return;
463 if (management_mode_ == MANAGEMENT_MODE_CONSUMER_MANAGED) {
464 // For consumer management enrollment, we don't store the policy.
465 ReportResult(EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_SUCCESS));
466 return;
469 enrollment_step_ = STEP_STORE_POLICY;
470 store_->InstallInitialPolicy(*policy_);
473 void EnrollmentHandlerChromeOS::Stop() {
474 if (client_.get())
475 client_->RemoveObserver(this);
476 enrollment_step_ = STEP_FINISHED;
477 weak_ptr_factory_.InvalidateWeakPtrs();
478 completion_callback_.Reset();
481 void EnrollmentHandlerChromeOS::ReportResult(EnrollmentStatus status) {
482 EnrollmentCallback callback = completion_callback_;
483 Stop();
485 if (status.status() != EnrollmentStatus::STATUS_SUCCESS) {
486 LOG(WARNING) << "Enrollment failed: " << status.status()
487 << ", client: " << status.client_status()
488 << ", validation: " << status.validation_status()
489 << ", store: " << status.store_status()
490 << ", lock: " << status.lock_status();
493 if (!callback.is_null())
494 callback.Run(status);
497 } // namespace policy