| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/policy/cloud_policy_controller.h" | 5 #include "chrome/browser/policy/cloud_policy_controller.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "base/time.h" | 15 #include "base/time.h" |
| 16 #include "chrome/browser/policy/cloud_policy_cache_base.h" | 16 #include "chrome/browser/policy/cloud_policy_cache_base.h" |
| 17 #include "chrome/browser/policy/cloud_policy_constants.h" |
| 17 #include "chrome/browser/policy/cloud_policy_subsystem.h" | 18 #include "chrome/browser/policy/cloud_policy_subsystem.h" |
| 18 #include "chrome/browser/policy/delayed_work_scheduler.h" | 19 #include "chrome/browser/policy/delayed_work_scheduler.h" |
| 19 #include "chrome/browser/policy/device_management_service.h" | 20 #include "chrome/browser/policy/device_management_service.h" |
| 20 #include "chrome/browser/policy/device_token_fetcher.h" | 21 #include "chrome/browser/policy/device_token_fetcher.h" |
| 21 #include "chrome/browser/policy/enterprise_metrics.h" | 22 #include "chrome/browser/policy/enterprise_metrics.h" |
| 22 #include "chrome/browser/policy/policy_notifier.h" | 23 #include "chrome/browser/policy/policy_notifier.h" |
| 23 #include "chrome/browser/policy/proto/device_management_constants.h" | |
| 24 #include "chrome/common/guid.h" | 24 #include "chrome/common/guid.h" |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 // The maximum ratio in percent of the policy refresh rate we use for adjusting | 28 // The maximum ratio in percent of the policy refresh rate we use for adjusting |
| 29 // the policy refresh time instant. The rationale is to avoid load spikes from | 29 // the policy refresh time instant. The rationale is to avoid load spikes from |
| 30 // many devices that were set up in sync for some reason. | 30 // many devices that were set up in sync for some reason. |
| 31 const int kPolicyRefreshDeviationFactorPercent = 10; | 31 const int kPolicyRefreshDeviationFactorPercent = 10; |
| 32 // Maximum deviation we are willing to accept. | 32 // Maximum deviation we are willing to accept. |
| 33 const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000; | 33 const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 // The controller doesn't have enough material to start a token fetch, | 116 // The controller doesn't have enough material to start a token fetch, |
| 117 // but observers of the cache are waiting for the refresh. | 117 // but observers of the cache are waiting for the refresh. |
| 118 SetState(STATE_TOKEN_UNMANAGED); | 118 SetState(STATE_TOKEN_UNMANAGED); |
| 119 } | 119 } |
| 120 } else { | 120 } else { |
| 121 // The token is valid, so the next step is to fetch policy. | 121 // The token is valid, so the next step is to fetch policy. |
| 122 SetState(STATE_TOKEN_VALID); | 122 SetState(STATE_TOKEN_VALID); |
| 123 } | 123 } |
| 124 } | 124 } |
| 125 | 125 |
| 126 void CloudPolicyController::HandlePolicyResponse( | 126 void CloudPolicyController::OnPolicyFetchCompleted( |
| 127 const em::DevicePolicyResponse& response) { | 127 DeviceManagementStatus status, |
| 128 if (response.response_size() > 0) { | 128 const em::DeviceManagementResponse& response) { |
| 129 if (response.response_size() > 1) { | 129 if (status == DM_STATUS_SUCCESS && !response.has_policy_response()) { |
| 130 LOG(WARNING) << "More than one policy in the response of the device " | 130 // Handled below. |
| 131 << "management server, discarding."; | 131 status = DM_STATUS_RESPONSE_DECODING_ERROR; |
| 132 } |
| 133 |
| 134 switch (status) { |
| 135 case DM_STATUS_SUCCESS: { |
| 136 const em::DevicePolicyResponse& policy_response( |
| 137 response.policy_response()); |
| 138 if (policy_response.response_size() > 0) { |
| 139 if (policy_response.response_size() > 1) { |
| 140 LOG(WARNING) << "More than one policy in the response of the device " |
| 141 << "management server, discarding."; |
| 142 } |
| 143 const em::PolicyFetchResponse& fetch_response( |
| 144 policy_response.response(0)); |
| 145 if (!fetch_response.has_error_code() || |
| 146 fetch_response.error_code() == dm_protocol::POLICY_FETCH_SUCCESS) { |
| 147 cache_->SetPolicy(fetch_response); |
| 148 SetState(STATE_POLICY_VALID); |
| 149 } else { |
| 150 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, |
| 151 kMetricPolicyFetchBadResponse, |
| 152 kMetricPolicySize); |
| 153 SetState(STATE_POLICY_UNAVAILABLE); |
| 154 } |
| 155 } else { |
| 156 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchBadResponse, |
| 157 kMetricPolicySize); |
| 158 SetState(STATE_POLICY_UNAVAILABLE); |
| 159 } |
| 160 return; |
| 132 } | 161 } |
| 133 if (!response.response(0).has_error_code() || | 162 case DM_STATUS_SERVICE_DEVICE_NOT_FOUND: |
| 134 response.response(0).error_code() == | 163 case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: |
| 135 DeviceManagementBackend::kPolicyFetchSuccess) { | 164 case DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID: |
| 136 cache_->SetPolicy(response.response(0)); | |
| 137 SetState(STATE_POLICY_VALID); | |
| 138 } else { | |
| 139 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchBadResponse, | |
| 140 kMetricPolicySize); | |
| 141 SetState(STATE_POLICY_UNAVAILABLE); | |
| 142 } | |
| 143 } else { | |
| 144 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchBadResponse, | |
| 145 kMetricPolicySize); | |
| 146 SetState(STATE_POLICY_UNAVAILABLE); | |
| 147 } | |
| 148 } | |
| 149 | |
| 150 void CloudPolicyController::OnError(DeviceManagementBackend::ErrorCode code) { | |
| 151 switch (code) { | |
| 152 case DeviceManagementBackend::kErrorServiceDeviceNotFound: | |
| 153 case DeviceManagementBackend::kErrorServiceDeviceIdConflict: | |
| 154 case DeviceManagementBackend::kErrorServiceManagementTokenInvalid: { | |
| 155 LOG(WARNING) << "The device token was either invalid or unknown to the " | 165 LOG(WARNING) << "The device token was either invalid or unknown to the " |
| 156 << "device manager, re-registering device."; | 166 << "device manager, re-registering device."; |
| 157 // Will retry fetching a token but gracefully backing off. | 167 // Will retry fetching a token but gracefully backing off. |
| 158 SetState(STATE_TOKEN_ERROR); | 168 SetState(STATE_TOKEN_ERROR); |
| 159 return; | 169 return; |
| 160 } | 170 case DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: |
| 161 case DeviceManagementBackend::kErrorServiceInvalidSerialNumber: { | |
| 162 VLOG(1) << "The device is no longer enlisted for the domain."; | 171 VLOG(1) << "The device is no longer enlisted for the domain."; |
| 163 token_fetcher_->SetSerialNumberInvalidState(); | 172 token_fetcher_->SetSerialNumberInvalidState(); |
| 164 SetState(STATE_TOKEN_ERROR); | 173 SetState(STATE_TOKEN_ERROR); |
| 165 return; | 174 return; |
| 166 } | 175 case DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED: |
| 167 case DeviceManagementBackend::kErrorServiceManagementNotSupported: { | |
| 168 VLOG(1) << "The device is no longer managed."; | 176 VLOG(1) << "The device is no longer managed."; |
| 169 token_fetcher_->SetUnmanagedState(); | 177 token_fetcher_->SetUnmanagedState(); |
| 170 SetState(STATE_TOKEN_UNMANAGED); | 178 SetState(STATE_TOKEN_UNMANAGED); |
| 171 return; | 179 return; |
| 172 } | 180 case DM_STATUS_SERVICE_POLICY_NOT_FOUND: |
| 173 case DeviceManagementBackend::kErrorServicePolicyNotFound: | 181 case DM_STATUS_REQUEST_INVALID: |
| 174 case DeviceManagementBackend::kErrorRequestInvalid: | 182 case DM_STATUS_SERVICE_ACTIVATION_PENDING: |
| 175 case DeviceManagementBackend::kErrorServiceActivationPending: | 183 case DM_STATUS_RESPONSE_DECODING_ERROR: |
| 176 case DeviceManagementBackend::kErrorResponseDecoding: | 184 case DM_STATUS_HTTP_STATUS_ERROR: |
| 177 case DeviceManagementBackend::kErrorHttpStatus: { | |
| 178 VLOG(1) << "An error in the communication with the policy server occurred" | 185 VLOG(1) << "An error in the communication with the policy server occurred" |
| 179 << ", will retry in a few hours."; | 186 << ", will retry in a few hours."; |
| 180 SetState(STATE_POLICY_UNAVAILABLE); | 187 SetState(STATE_POLICY_UNAVAILABLE); |
| 181 return; | 188 return; |
| 182 } | 189 case DM_STATUS_REQUEST_FAILED: |
| 183 case DeviceManagementBackend::kErrorRequestFailed: | 190 case DM_STATUS_TEMPORARY_UNAVAILABLE: |
| 184 case DeviceManagementBackend::kErrorTemporaryUnavailable: { | |
| 185 VLOG(1) << "A temporary error in the communication with the policy server" | 191 VLOG(1) << "A temporary error in the communication with the policy server" |
| 186 << " occurred."; | 192 << " occurred."; |
| 187 // Will retry last operation but gracefully backing off. | 193 // Will retry last operation but gracefully backing off. |
| 188 SetState(STATE_POLICY_ERROR); | 194 SetState(STATE_POLICY_ERROR); |
| 189 return; | 195 return; |
| 190 } | |
| 191 } | 196 } |
| 192 | 197 |
| 193 NOTREACHED(); | 198 NOTREACHED(); |
| 194 SetState(STATE_POLICY_ERROR); | 199 SetState(STATE_POLICY_ERROR); |
| 195 } | 200 } |
| 196 | 201 |
| 197 void CloudPolicyController::OnDeviceTokenChanged() { | 202 void CloudPolicyController::OnDeviceTokenChanged() { |
| 198 if (data_store_->device_token().empty()) | 203 if (data_store_->device_token().empty()) |
| 199 SetState(STATE_TOKEN_UNAVAILABLE); | 204 SetState(STATE_TOKEN_UNAVAILABLE); |
| 200 else | 205 else |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 token_fetcher_->FetchToken(); | 277 token_fetcher_->FetchToken(); |
| 273 } else { | 278 } else { |
| 274 SetState(STATE_TOKEN_UNMANAGED); | 279 SetState(STATE_TOKEN_UNMANAGED); |
| 275 } | 280 } |
| 276 } else { | 281 } else { |
| 277 VLOG(1) << "Not ready to fetch DMToken yet, will try again later."; | 282 VLOG(1) << "Not ready to fetch DMToken yet, will try again later."; |
| 278 } | 283 } |
| 279 } | 284 } |
| 280 | 285 |
| 281 void CloudPolicyController::SendPolicyRequest() { | 286 void CloudPolicyController::SendPolicyRequest() { |
| 282 backend_.reset(service_->CreateBackend()); | |
| 283 DCHECK(!data_store_->device_token().empty()); | 287 DCHECK(!data_store_->device_token().empty()); |
| 284 em::DevicePolicyRequest policy_request; | 288 request_job_.reset( |
| 285 em::PolicyFetchRequest* fetch_request = policy_request.add_request(); | 289 service_->CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH)); |
| 290 request_job_->SetDMToken(data_store_->device_token()); |
| 291 request_job_->SetClientID(data_store_->device_id()); |
| 292 request_job_->SetUserAffiliation(data_store_->user_affiliation()); |
| 293 |
| 294 em::DeviceManagementRequest* request = request_job_->GetRequest(); |
| 295 em::PolicyFetchRequest* fetch_request = |
| 296 request->mutable_policy_request()->add_request(); |
| 286 em::DeviceStatusReportRequest device_status; | 297 em::DeviceStatusReportRequest device_status; |
| 287 fetch_request->set_signature_type(em::PolicyFetchRequest::SHA1_RSA); | 298 fetch_request->set_signature_type(em::PolicyFetchRequest::SHA1_RSA); |
| 288 fetch_request->set_policy_type(data_store_->policy_type()); | 299 fetch_request->set_policy_type(data_store_->policy_type()); |
| 289 if (cache_->machine_id_missing() && !data_store_->machine_id().empty()) | 300 if (cache_->machine_id_missing() && !data_store_->machine_id().empty()) |
| 290 fetch_request->set_machine_id(data_store_->machine_id()); | 301 fetch_request->set_machine_id(data_store_->machine_id()); |
| 291 if (!cache_->is_unmanaged() && | 302 if (!cache_->is_unmanaged() && |
| 292 !cache_->last_policy_refresh_time().is_null()) { | 303 !cache_->last_policy_refresh_time().is_null()) { |
| 293 base::TimeDelta timestamp = | 304 base::TimeDelta timestamp = |
| 294 cache_->last_policy_refresh_time() - base::Time::UnixEpoch(); | 305 cache_->last_policy_refresh_time() - base::Time::UnixEpoch(); |
| 295 fetch_request->set_timestamp(timestamp.InMilliseconds()); | 306 fetch_request->set_timestamp(timestamp.InMilliseconds()); |
| 296 } | 307 } |
| 297 int key_version = 0; | 308 int key_version = 0; |
| 298 if (cache_->GetPublicKeyVersion(&key_version)) | 309 if (cache_->GetPublicKeyVersion(&key_version)) |
| 299 fetch_request->set_public_key_version(key_version); | 310 fetch_request->set_public_key_version(key_version); |
| 300 | 311 |
| 301 #if defined(OS_CHROMEOS) | 312 #if defined(OS_CHROMEOS) |
| 302 if (data_store_->device_status_collector()) | 313 if (data_store_->device_status_collector()) { |
| 303 data_store_->device_status_collector()->GetStatus(&device_status); | 314 data_store_->device_status_collector()->GetStatus( |
| 315 request->mutable_device_status_report_request()); |
| 316 } |
| 304 #endif | 317 #endif |
| 305 | 318 |
| 306 backend_->ProcessPolicyRequest(data_store_->device_token(), | 319 request_job_->Start(base::Bind(&CloudPolicyController::OnPolicyFetchCompleted, |
| 307 data_store_->device_id(), | 320 base::Unretained(this))); |
| 308 data_store_->user_affiliation(), | |
| 309 policy_request, &device_status, this); | |
| 310 } | 321 } |
| 311 | 322 |
| 312 void CloudPolicyController::DoWork() { | 323 void CloudPolicyController::DoWork() { |
| 313 switch (state_) { | 324 switch (state_) { |
| 314 case STATE_TOKEN_UNAVAILABLE: | 325 case STATE_TOKEN_UNAVAILABLE: |
| 315 case STATE_TOKEN_ERROR: | 326 case STATE_TOKEN_ERROR: |
| 316 FetchToken(); | 327 FetchToken(); |
| 317 return; | 328 return; |
| 318 case STATE_TOKEN_VALID: | 329 case STATE_TOKEN_VALID: |
| 319 case STATE_POLICY_VALID: | 330 case STATE_POLICY_VALID: |
| 320 case STATE_POLICY_ERROR: | 331 case STATE_POLICY_ERROR: |
| 321 case STATE_POLICY_UNAVAILABLE: | 332 case STATE_POLICY_UNAVAILABLE: |
| 322 SendPolicyRequest(); | 333 SendPolicyRequest(); |
| 323 return; | 334 return; |
| 324 case STATE_TOKEN_UNMANAGED: | 335 case STATE_TOKEN_UNMANAGED: |
| 325 return; | 336 return; |
| 326 } | 337 } |
| 327 | 338 |
| 328 NOTREACHED() << "Unhandled state" << state_; | 339 NOTREACHED() << "Unhandled state" << state_; |
| 329 } | 340 } |
| 330 | 341 |
| 331 void CloudPolicyController::SetState( | 342 void CloudPolicyController::SetState( |
| 332 CloudPolicyController::ControllerState new_state) { | 343 CloudPolicyController::ControllerState new_state) { |
| 333 state_ = new_state; | 344 state_ = new_state; |
| 334 | 345 |
| 335 backend_.reset(); // Stop any pending requests. | 346 request_job_.reset(); // Stop any pending requests. |
| 336 | 347 |
| 337 base::Time now(base::Time::NowFromSystemTime()); | 348 base::Time now(base::Time::NowFromSystemTime()); |
| 338 base::Time refresh_at; | 349 base::Time refresh_at; |
| 339 base::Time last_refresh(cache_->last_policy_refresh_time()); | 350 base::Time last_refresh(cache_->last_policy_refresh_time()); |
| 340 if (last_refresh.is_null()) | 351 if (last_refresh.is_null()) |
| 341 last_refresh = now; | 352 last_refresh = now; |
| 342 | 353 |
| 343 // Determine when to take the next step. | 354 // Determine when to take the next step. |
| 344 bool inform_notifier_done = false; | 355 bool inform_notifier_done = false; |
| 345 switch (state_) { | 356 switch (state_) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 } | 424 } |
| 414 | 425 |
| 415 int64 CloudPolicyController::GetRefreshDelay() { | 426 int64 CloudPolicyController::GetRefreshDelay() { |
| 416 int64 deviation = (kPolicyRefreshDeviationFactorPercent * | 427 int64 deviation = (kPolicyRefreshDeviationFactorPercent * |
| 417 policy_refresh_rate_ms_) / 100; | 428 policy_refresh_rate_ms_) / 100; |
| 418 deviation = std::min(deviation, kPolicyRefreshDeviationMaxInMilliseconds); | 429 deviation = std::min(deviation, kPolicyRefreshDeviationMaxInMilliseconds); |
| 419 return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1); | 430 return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1); |
| 420 } | 431 } |
| 421 | 432 |
| 422 } // namespace policy | 433 } // namespace policy |
| OLD | NEW |