enrollment_handler_chromeos.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/policy/enrollment_handler_chromeos.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/browser_process.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/policy/cloud/cloud_policy_constants.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_urls.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace em = enterprise_management; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Retry for InstallAttrs initialization every 500ms. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kLockRetryIntervalMs = 500; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum time to retry InstallAttrs initialization before we give up. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kLockRetryTimeoutMs = 10 * 60 * 1000; // 10 minutes. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnrollmentHandlerChromeOS::EnrollmentHandlerChromeOS( 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeviceCloudPolicyStoreChromeOS* store, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnterpriseInstallAttributes* install_attributes, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<CloudPolicyClient> client, 368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> background_task_runner, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& client_id, 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_auto_enrollment, 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& requisition, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AllowedDeviceModes& allowed_device_modes, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EnrollmentCallback& completion_callback) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : store_(store), 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_attributes_(install_attributes), 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_(client.Pass()), 468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) background_task_runner_(background_task_runner), 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_token_(auth_token), 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_id_(client_id), 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_auto_enrollment_(is_auto_enrollment), 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) requisition_(requisition), 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allowed_device_modes_(allowed_device_modes), 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion_callback_(completion_callback), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_mode_(DEVICE_MODE_NOT_SET), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enrollment_step_(STEP_PENDING), 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lockbox_init_duration_(0), 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!client_->is_registered()); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(DM_STATUS_SUCCESS, client_->status()); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) store_->AddObserver(this); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_->AddObserver(this); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_->AddNamespaceToFetch(PolicyNamespaceKey( 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dm_protocol::kChromeDevicePolicyType, std::string())); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnrollmentHandlerChromeOS::~EnrollmentHandlerChromeOS() { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) store_->RemoveObserver(this); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::StartEnrollment() { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(STEP_PENDING, enrollment_step_); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enrollment_step_ = STEP_LOADING_STORE; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AttemptRegistration(); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<CloudPolicyClient> EnrollmentHandlerChromeOS::ReleaseClient() { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return client_.Pass(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::OnPolicyFetched(CloudPolicyClient* client) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(client_.get(), client); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(STEP_POLICY_FETCH, enrollment_step_); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enrollment_step_ = STEP_VALIDATION; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate the policy. 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const em::PolicyFetchResponse* policy = client_->GetPolicyFor( 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PolicyNamespaceKey(dm_protocol::kChromeDevicePolicyType, std::string())); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!policy) { 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ReportResult(EnrollmentStatus::ForFetchError( 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DM_STATUS_RESPONSE_DECODING_ERROR)); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<DeviceCloudPolicyValidator> validator( 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeviceCloudPolicyValidator::Create( 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<em::PolicyFetchResponse>( 998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) new em::PolicyFetchResponse(*policy)), 1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) background_task_runner_)); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) validator->ValidateTimestamp(base::Time(), base::Time::NowFromSystemTime(), 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CloudPolicyValidatorBase::TIMESTAMP_REQUIRED); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (install_attributes_->IsEnterpriseDevice()) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) validator->ValidateDomain(install_attributes_->GetDomain()); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) validator->ValidateDMToken(client->dm_token(), 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CloudPolicyValidatorBase::DM_TOKEN_REQUIRED); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) validator->ValidatePolicyType(dm_protocol::kChromeDevicePolicyType); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) validator->ValidatePayload(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) validator->ValidateInitialKey(); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) validator.release()->StartValidation( 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&EnrollmentHandlerChromeOS::PolicyValidated, 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weak_factory_.GetWeakPtr())); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::OnRegistrationStateChanged( 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloudPolicyClient* client) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(client_.get(), client); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (enrollment_step_ == STEP_REGISTRATION && client_->is_registered()) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enrollment_step_ = STEP_POLICY_FETCH, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_mode_ = client_->device_mode(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (device_mode_ == DEVICE_MODE_NOT_SET) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_mode_ = DEVICE_MODE_ENTERPRISE; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!allowed_device_modes_.test(device_mode_)) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Bad device mode " << device_mode_; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(EnrollmentStatus::ForStatus( 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_->FetchPolicy(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(FATAL) << "Registration state changed to " << client_->is_registered() 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " in step " << enrollment_step_; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::OnClientError(CloudPolicyClient* client) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(client_.get(), client); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (enrollment_step_ == STEP_ROBOT_AUTH_FETCH) { 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(WARNING) << "API authentication code fetch failed: " 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << client_->status(); 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Robot auth tokens are currently optional. Skip fetching the refresh 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // token and jump directly to the lock device step. 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) robot_refresh_token_.clear(); 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DoLockDeviceStep(); 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (enrollment_step_ < STEP_POLICY_FETCH) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(EnrollmentStatus::ForRegistrationError(client_->status())); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(EnrollmentStatus::ForFetchError(client_->status())); 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::OnStoreLoaded(CloudPolicyStore* store) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(store_, store); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (enrollment_step_ == STEP_LOADING_STORE) { 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If the |store_| wasn't initialized when StartEnrollment() was 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // called, then AttemptRegistration() bails silently. This gets 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // registration rolling again after the store finishes loading. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AttemptRegistration(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (enrollment_step_ == STEP_STORE_POLICY) { 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Store the robot API auth refresh token. 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Currently optional, so always return success. 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chromeos::DeviceOAuth2TokenService* token_service = 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chromeos::DeviceOAuth2TokenServiceFactory::Get(); 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (token_service && !robot_refresh_token_.empty()) { 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_service->SetAndSaveRefreshToken(robot_refresh_token_); 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_SUCCESS)); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::OnStoreError(CloudPolicyStore* store) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(store_, store); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(EnrollmentStatus::ForStoreError(store_->status(), 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) store_->validation_status())); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::AttemptRegistration() { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(STEP_LOADING_STORE, enrollment_step_); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (store_->is_initialized()) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enrollment_step_ = STEP_REGISTRATION; 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_->Register(em::DeviceRegisterRequest::DEVICE, 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) auth_token_, client_id_, is_auto_enrollment_, 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) requisition_); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::PolicyValidated( 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeviceCloudPolicyValidator* validator) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(STEP_VALIDATION, enrollment_step_); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (validator->success()) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) policy_ = validator->policy().Pass(); 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) username_ = validator->policy_data()->username(); 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device_id_ = validator->policy_data()->device_id(); 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) enrollment_step_ = STEP_ROBOT_AUTH_FETCH; 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) client_->FetchRobotAuthCodes(auth_token_); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(EnrollmentStatus::ForValidationError(validator->status())); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::OnRobotAuthCodesFetched( 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CloudPolicyClient* client) { 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(client_.get(), client); 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK_EQ(STEP_ROBOT_AUTH_FETCH, enrollment_step_); 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) enrollment_step_ = STEP_ROBOT_AUTH_REFRESH; 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gaia::OAuthClientInfo client_info; 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) client_info.client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id(); 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) client_info.client_secret = 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_secret(); 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) client_info.redirect_uri = "oob"; 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Use the system request context to avoid sending user cookies. 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gaia_oauth_client_.reset(new gaia::GaiaOAuthClient( 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) g_browser_process->system_request_context())); 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gaia_oauth_client_->GetTokensFromAuthCode(client_info, 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) client->robot_api_auth_code(), 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0 /* max_retries */, 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this); 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// GaiaOAuthClient::Delegate callback for OAuth2 refresh token fetched. 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::OnGetTokensResponse( 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& refresh_token, 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& access_token, 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int expires_in_seconds) { 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_); 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) robot_refresh_token_ = refresh_token; 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DoLockDeviceStep(); 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::DoLockDeviceStep() { 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) enrollment_step_ = STEP_LOCK_DEVICE, 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StartLockDevice(username_, device_mode_, device_id_); 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// GaiaOAuthClient::Delegate 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::OnRefreshTokenResponse( 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& access_token, 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int expires_in_seconds) { 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We never use the code that should trigger this callback. 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(FATAL) << "Unexpected callback invoked"; 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// GaiaOAuthClient::Delegate OAuth2 error when fetching refresh token request. 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::OnOAuthError() { 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_); 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DoLockDeviceStep(); 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// GaiaOAuthClient::Delegate network error when fetching refresh token. 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::OnNetworkError(int response_code) { 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Network error while fetching API refresh token: " 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << response_code; 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_); 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DoLockDeviceStep(); 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::StartLockDevice( 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& user, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeviceMode device_mode, 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& device_id) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since this method is also called directly. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) install_attributes_->LockDevice( 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user, device_mode, device_id, 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&EnrollmentHandlerChromeOS::HandleLockDeviceResult, 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr(), 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user, 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device_mode, 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device_id)); 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::HandleLockDeviceResult( 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& user, 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DeviceMode device_mode, 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& device_id, 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnterpriseInstallAttributes::LockResult lock_result) { 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (lock_result) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EnterpriseInstallAttributes::LOCK_SUCCESS: 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enrollment_step_ = STEP_STORE_POLICY; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) store_->InstallInitialPolicy(*policy_); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EnterpriseInstallAttributes::LOCK_NOT_READY: 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We wait up to |kLockRetryTimeoutMs| milliseconds and if it hasn't 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // succeeded by then show an error to the user and stop the enrollment. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lockbox_init_duration_ < kLockRetryTimeoutMs) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // InstallAttributes not ready yet, retry later. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Install Attributes not ready yet will retry in " 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << kLockRetryIntervalMs << "ms."; 30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&EnrollmentHandlerChromeOS::StartLockDevice, 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.GetWeakPtr(), 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user, device_mode, device_id), 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kLockRetryIntervalMs)); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lockbox_init_duration_ += kLockRetryIntervalMs; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(EnrollmentStatus::ForStatus( 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnrollmentStatus::STATUS_LOCK_TIMEOUT)); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EnterpriseInstallAttributes::LOCK_BACKEND_ERROR: 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(EnrollmentStatus::ForStatus( 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnrollmentStatus::STATUS_LOCK_ERROR)); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EnterpriseInstallAttributes::LOCK_WRONG_USER: 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Enrollment cannot proceed because the InstallAttrs " 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "has been locked already!"; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(EnrollmentStatus::ForStatus( 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnrollmentStatus::STATUS_LOCK_WRONG_USER)); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Invalid lock result " << lock_result; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(EnrollmentStatus::ForStatus( 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnrollmentStatus::STATUS_LOCK_ERROR)); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::Stop() { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (client_.get()) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_->RemoveObserver(this); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enrollment_step_ = STEP_FINISHED; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion_callback_.Reset(); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::ReportResult(EnrollmentStatus status) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnrollmentCallback callback = completion_callback_; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.status() != EnrollmentStatus::STATUS_SUCCESS) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Enrollment failed: " << status.status() 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " " << status.client_status() 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " " << status.validation_status() 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " " << status.store_status(); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!callback.is_null()) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(status); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace policy 356