enrollment_handler_chromeos.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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. 4 5#include "chrome/browser/chromeos/policy/enrollment_handler_chromeos.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "base/message_loop.h" 10#include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h" 11#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h" 12#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" 13#include "chrome/browser/policy/cloud/cloud_policy_constants.h" 14#include "chrome/browser/policy/cloud/proto/device_management_backend.pb.h" 15 16namespace em = enterprise_management; 17 18namespace policy { 19 20namespace { 21 22// Retry for InstallAttrs initialization every 500ms. 23const int kLockRetryIntervalMs = 500; 24// Maximum time to retry InstallAttrs initialization before we give up. 25const int kLockRetryTimeoutMs = 10 * 60 * 1000; // 10 minutes. 26 27} // namespace 28 29EnrollmentHandlerChromeOS::EnrollmentHandlerChromeOS( 30 DeviceCloudPolicyStoreChromeOS* store, 31 EnterpriseInstallAttributes* install_attributes, 32 scoped_ptr<CloudPolicyClient> client, 33 const std::string& auth_token, 34 const std::string& client_id, 35 bool is_auto_enrollment, 36 const AllowedDeviceModes& allowed_device_modes, 37 const EnrollmentCallback& completion_callback) 38 : store_(store), 39 install_attributes_(install_attributes), 40 client_(client.Pass()), 41 auth_token_(auth_token), 42 client_id_(client_id), 43 is_auto_enrollment_(is_auto_enrollment), 44 allowed_device_modes_(allowed_device_modes), 45 completion_callback_(completion_callback), 46 device_mode_(DEVICE_MODE_NOT_SET), 47 enrollment_step_(STEP_PENDING), 48 lockbox_init_duration_(0), 49 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { 50 CHECK(!client_->is_registered()); 51 CHECK_EQ(DM_STATUS_SUCCESS, client_->status()); 52 store_->AddObserver(this); 53 client_->AddObserver(this); 54 client_->AddNamespaceToFetch(PolicyNamespaceKey( 55 dm_protocol::kChromeDevicePolicyType, std::string())); 56} 57 58EnrollmentHandlerChromeOS::~EnrollmentHandlerChromeOS() { 59 Stop(); 60 store_->RemoveObserver(this); 61} 62 63void EnrollmentHandlerChromeOS::StartEnrollment() { 64 CHECK_EQ(STEP_PENDING, enrollment_step_); 65 enrollment_step_ = STEP_LOADING_STORE; 66 AttemptRegistration(); 67} 68 69scoped_ptr<CloudPolicyClient> EnrollmentHandlerChromeOS::ReleaseClient() { 70 Stop(); 71 return client_.Pass(); 72} 73 74void EnrollmentHandlerChromeOS::OnPolicyFetched(CloudPolicyClient* client) { 75 DCHECK_EQ(client_.get(), client); 76 CHECK_EQ(STEP_POLICY_FETCH, enrollment_step_); 77 78 enrollment_step_ = STEP_VALIDATION; 79 80 // Validate the policy. 81 const em::PolicyFetchResponse* policy = client_->GetPolicyFor( 82 PolicyNamespaceKey(dm_protocol::kChromeDevicePolicyType, std::string())); 83 if (!policy) { 84 ReportResult(EnrollmentStatus::ForFetchError( 85 DM_STATUS_RESPONSE_DECODING_ERROR)); 86 return; 87 } 88 89 scoped_ptr<DeviceCloudPolicyValidator> validator( 90 DeviceCloudPolicyValidator::Create( 91 scoped_ptr<em::PolicyFetchResponse>( 92 new em::PolicyFetchResponse(*policy)))); 93 94 validator->ValidateTimestamp(base::Time(), base::Time::NowFromSystemTime(), 95 CloudPolicyValidatorBase::TIMESTAMP_REQUIRED); 96 if (install_attributes_->IsEnterpriseDevice()) 97 validator->ValidateDomain(install_attributes_->GetDomain()); 98 validator->ValidateDMToken(client->dm_token(), 99 CloudPolicyValidatorBase::DM_TOKEN_REQUIRED); 100 validator->ValidatePolicyType(dm_protocol::kChromeDevicePolicyType); 101 validator->ValidatePayload(); 102 validator->ValidateInitialKey(); 103 validator.release()->StartValidation( 104 base::Bind(&EnrollmentHandlerChromeOS::PolicyValidated, 105 weak_factory_.GetWeakPtr())); 106} 107 108void EnrollmentHandlerChromeOS::OnRegistrationStateChanged( 109 CloudPolicyClient* client) { 110 DCHECK_EQ(client_.get(), client); 111 112 if (enrollment_step_ == STEP_REGISTRATION && client_->is_registered()) { 113 enrollment_step_ = STEP_POLICY_FETCH, 114 device_mode_ = client_->device_mode(); 115 if (device_mode_ == DEVICE_MODE_NOT_SET) 116 device_mode_ = DEVICE_MODE_ENTERPRISE; 117 if (!allowed_device_modes_.test(device_mode_)) { 118 LOG(ERROR) << "Bad device mode " << device_mode_; 119 ReportResult(EnrollmentStatus::ForStatus( 120 EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE)); 121 return; 122 } 123 client_->FetchPolicy(); 124 } else { 125 LOG(FATAL) << "Registration state changed to " << client_->is_registered() 126 << " in step " << enrollment_step_; 127 } 128} 129 130void EnrollmentHandlerChromeOS::OnClientError(CloudPolicyClient* client) { 131 DCHECK_EQ(client_.get(), client); 132 133 if (enrollment_step_ < STEP_POLICY_FETCH) 134 ReportResult(EnrollmentStatus::ForRegistrationError(client_->status())); 135 else 136 ReportResult(EnrollmentStatus::ForFetchError(client_->status())); 137} 138 139void EnrollmentHandlerChromeOS::OnStoreLoaded(CloudPolicyStore* store) { 140 DCHECK_EQ(store_, store); 141 142 if (enrollment_step_ == STEP_LOADING_STORE) { 143 AttemptRegistration(); 144 } else if (enrollment_step_ == STEP_STORE_POLICY) { 145 ReportResult(EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_SUCCESS)); 146 } 147} 148 149void EnrollmentHandlerChromeOS::OnStoreError(CloudPolicyStore* store) { 150 DCHECK_EQ(store_, store); 151 ReportResult(EnrollmentStatus::ForStoreError(store_->status(), 152 store_->validation_status())); 153} 154 155void EnrollmentHandlerChromeOS::AttemptRegistration() { 156 CHECK_EQ(STEP_LOADING_STORE, enrollment_step_); 157 if (store_->is_initialized()) { 158 enrollment_step_ = STEP_REGISTRATION; 159 client_->Register(em::DeviceRegisterRequest::DEVICE, 160 auth_token_, client_id_, is_auto_enrollment_); 161 } 162} 163 164void EnrollmentHandlerChromeOS::PolicyValidated( 165 DeviceCloudPolicyValidator* validator) { 166 CHECK_EQ(STEP_VALIDATION, enrollment_step_); 167 if (validator->success()) { 168 policy_ = validator->policy().Pass(); 169 enrollment_step_ = STEP_LOCK_DEVICE; 170 WriteInstallAttributes(validator->policy_data()->username(), device_mode_, 171 validator->policy_data()->device_id()); 172 } else { 173 ReportResult(EnrollmentStatus::ForValidationError(validator->status())); 174 } 175} 176 177void EnrollmentHandlerChromeOS::WriteInstallAttributes( 178 const std::string& user, 179 DeviceMode device_mode, 180 const std::string& device_id) { 181 CHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_); 182 // Since this method is also called directly. 183 weak_factory_.InvalidateWeakPtrs(); 184 185 EnterpriseInstallAttributes::LockResult lock_result = 186 install_attributes_->LockDevice(user, device_mode, device_id); 187 switch (lock_result) { 188 case EnterpriseInstallAttributes::LOCK_SUCCESS: 189 enrollment_step_ = STEP_STORE_POLICY; 190 store_->InstallInitialPolicy(*policy_); 191 return; 192 case EnterpriseInstallAttributes::LOCK_NOT_READY: 193 // We wait up to |kLockRetryTimeoutMs| milliseconds and if it hasn't 194 // succeeded by then show an error to the user and stop the enrollment. 195 if (lockbox_init_duration_ < kLockRetryTimeoutMs) { 196 // InstallAttributes not ready yet, retry later. 197 LOG(WARNING) << "Install Attributes not ready yet will retry in " 198 << kLockRetryIntervalMs << "ms."; 199 MessageLoop::current()->PostDelayedTask( 200 FROM_HERE, 201 base::Bind(&EnrollmentHandlerChromeOS::WriteInstallAttributes, 202 weak_factory_.GetWeakPtr(), 203 user, device_mode, device_id), 204 base::TimeDelta::FromMilliseconds(kLockRetryIntervalMs)); 205 lockbox_init_duration_ += kLockRetryIntervalMs; 206 } else { 207 ReportResult(EnrollmentStatus::ForStatus( 208 EnrollmentStatus::STATUS_LOCK_TIMEOUT)); 209 } 210 return; 211 case EnterpriseInstallAttributes::LOCK_BACKEND_ERROR: 212 ReportResult(EnrollmentStatus::ForStatus( 213 EnrollmentStatus::STATUS_LOCK_ERROR)); 214 return; 215 case EnterpriseInstallAttributes::LOCK_WRONG_USER: 216 LOG(ERROR) << "Enrollment cannot proceed because the InstallAttrs " 217 << "has been locked already!"; 218 ReportResult(EnrollmentStatus::ForStatus( 219 EnrollmentStatus::STATUS_LOCK_WRONG_USER)); 220 return; 221 } 222 223 NOTREACHED() << "Invalid lock result " << lock_result; 224 ReportResult(EnrollmentStatus::ForStatus( 225 EnrollmentStatus::STATUS_LOCK_ERROR)); 226} 227 228void EnrollmentHandlerChromeOS::Stop() { 229 if (client_.get()) 230 client_->RemoveObserver(this); 231 enrollment_step_ = STEP_FINISHED; 232 weak_factory_.InvalidateWeakPtrs(); 233 completion_callback_.Reset(); 234} 235 236void EnrollmentHandlerChromeOS::ReportResult(EnrollmentStatus status) { 237 EnrollmentCallback callback = completion_callback_; 238 Stop(); 239 240 if (status.status() != EnrollmentStatus::STATUS_SUCCESS) { 241 LOG(WARNING) << "Enrollment failed: " << status.status() 242 << " " << status.client_status() 243 << " " << status.validation_status() 244 << " " << status.store_status(); 245 } 246 247 if (!callback.is_null()) 248 callback.Run(status); 249} 250 251} // namespace policy 252