| OLD | NEW |
| (Empty) |
| 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/policy/device_policy_cache.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "base/memory/scoped_ptr.h" | |
| 10 #include "base/metrics/histogram.h" | |
| 11 #include "base/values.h" | |
| 12 #include "chrome/browser/policy/cloud_policy_data_store.h" | |
| 13 #include "chrome/browser/policy/device_policy_decoder_chromeos.h" | |
| 14 #include "chrome/browser/policy/enterprise_install_attributes.h" | |
| 15 #include "chrome/browser/policy/enterprise_metrics.h" | |
| 16 #include "chrome/browser/policy/policy_map.h" | |
| 17 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h" | |
| 18 #include "chrome/browser/policy/proto/device_management_backend.pb.h" | |
| 19 #include "chrome/browser/policy/proto/device_management_local.pb.h" | |
| 20 #include "google_apis/gaia/gaia_auth_util.h" | |
| 21 | |
| 22 namespace em = enterprise_management; | |
| 23 | |
| 24 namespace policy { | |
| 25 | |
| 26 DevicePolicyCache::DevicePolicyCache( | |
| 27 CloudPolicyDataStore* data_store, | |
| 28 EnterpriseInstallAttributes* install_attributes) | |
| 29 : data_store_(data_store), | |
| 30 install_attributes_(install_attributes), | |
| 31 device_settings_service_(chromeos::DeviceSettingsService::Get()), | |
| 32 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | |
| 33 policy_fetch_pending_(false) { | |
| 34 device_settings_service_->AddObserver(this); | |
| 35 } | |
| 36 | |
| 37 DevicePolicyCache::DevicePolicyCache( | |
| 38 CloudPolicyDataStore* data_store, | |
| 39 EnterpriseInstallAttributes* install_attributes, | |
| 40 chromeos::DeviceSettingsService* device_settings_service) | |
| 41 : data_store_(data_store), | |
| 42 install_attributes_(install_attributes), | |
| 43 device_settings_service_(device_settings_service), | |
| 44 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | |
| 45 policy_fetch_pending_(false) { | |
| 46 device_settings_service_->AddObserver(this); | |
| 47 } | |
| 48 | |
| 49 DevicePolicyCache::~DevicePolicyCache() { | |
| 50 device_settings_service_->RemoveObserver(this); | |
| 51 } | |
| 52 | |
| 53 void DevicePolicyCache::Load() { | |
| 54 DeviceSettingsUpdated(); | |
| 55 } | |
| 56 | |
| 57 bool DevicePolicyCache::SetPolicy(const em::PolicyFetchResponse& policy) { | |
| 58 DCHECK(IsReady()); | |
| 59 | |
| 60 // Make sure we have an enterprise device. | |
| 61 std::string registration_domain(install_attributes_->GetDomain()); | |
| 62 if (registration_domain.empty()) { | |
| 63 LOG(WARNING) << "Refusing to accept policy on non-enterprise device."; | |
| 64 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, | |
| 65 kMetricPolicyFetchNonEnterpriseDevice, | |
| 66 kMetricPolicySize); | |
| 67 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 68 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
| 69 return false; | |
| 70 } | |
| 71 | |
| 72 // Check the user this policy is for against the device-locked name. | |
| 73 em::PolicyData policy_data; | |
| 74 if (!policy_data.ParseFromString(policy.policy_data())) { | |
| 75 LOG(WARNING) << "Invalid policy protobuf"; | |
| 76 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchInvalidPolicy, | |
| 77 kMetricPolicySize); | |
| 78 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 79 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
| 80 return false; | |
| 81 } | |
| 82 | |
| 83 // Existing installations may not have a canonicalized version of the | |
| 84 // registration domain in install attributes, so lower-case the data here. | |
| 85 if (registration_domain != gaia::ExtractDomainName(policy_data.username())) { | |
| 86 LOG(WARNING) << "Refusing policy blob for " << policy_data.username() | |
| 87 << " which doesn't match domain " << registration_domain; | |
| 88 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchUserMismatch, | |
| 89 kMetricPolicySize); | |
| 90 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 91 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
| 92 return false; | |
| 93 } | |
| 94 | |
| 95 set_last_policy_refresh_time(base::Time::NowFromSystemTime()); | |
| 96 | |
| 97 // Start a store operation. | |
| 98 policy_fetch_pending_ = true; | |
| 99 device_settings_service_->Store( | |
| 100 scoped_ptr<em::PolicyFetchResponse>(new em::PolicyFetchResponse(policy)), | |
| 101 base::Bind(&DevicePolicyCache::PolicyStoreOpCompleted, | |
| 102 weak_ptr_factory_.GetWeakPtr())); | |
| 103 return true; | |
| 104 } | |
| 105 | |
| 106 void DevicePolicyCache::SetUnmanaged() { | |
| 107 LOG(WARNING) << "Tried to set DevicePolicyCache to 'unmanaged'!"; | |
| 108 // This is not supported for DevicePolicyCache. | |
| 109 } | |
| 110 | |
| 111 void DevicePolicyCache::SetFetchingDone() { | |
| 112 // Don't send the notification just yet if there is a pending policy | |
| 113 // store/reload cycle. | |
| 114 if (!policy_fetch_pending_) | |
| 115 CloudPolicyCacheBase::SetFetchingDone(); | |
| 116 } | |
| 117 | |
| 118 void DevicePolicyCache::OwnershipStatusChanged() {} | |
| 119 | |
| 120 void DevicePolicyCache::DeviceSettingsUpdated() { | |
| 121 DCHECK(CalledOnValidThread()); | |
| 122 chromeos::DeviceSettingsService::Status status = | |
| 123 device_settings_service_->status(); | |
| 124 const em::PolicyData* policy_data = device_settings_service_->policy_data(); | |
| 125 if (status == chromeos::DeviceSettingsService::STORE_SUCCESS && | |
| 126 !policy_data) { | |
| 127 // Initial policy load is still pending. | |
| 128 return; | |
| 129 } | |
| 130 | |
| 131 if (!IsReady()) { | |
| 132 std::string device_token; | |
| 133 InstallInitialPolicy(status, policy_data, &device_token); | |
| 134 SetTokenAndFlagReady(device_token); | |
| 135 } else { // In other words, IsReady() == true | |
| 136 if (status != chromeos::DeviceSettingsService::STORE_SUCCESS || | |
| 137 !policy_data) { | |
| 138 if (status == chromeos::DeviceSettingsService::STORE_VALIDATION_ERROR) { | |
| 139 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchBadSignature, | |
| 140 kMetricPolicySize); | |
| 141 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 142 CloudPolicySubsystem::SIGNATURE_MISMATCH); | |
| 143 } else { | |
| 144 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchOtherFailed, | |
| 145 kMetricPolicySize); | |
| 146 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 147 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
| 148 } | |
| 149 } else { | |
| 150 em::PolicyFetchResponse policy_response; | |
| 151 CHECK(policy_data->SerializeToString( | |
| 152 policy_response.mutable_policy_data())); | |
| 153 bool ok = SetPolicyInternal(policy_response, NULL, false); | |
| 154 if (ok) { | |
| 155 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchOK, | |
| 156 kMetricPolicySize); | |
| 157 } | |
| 158 } | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 bool DevicePolicyCache::DecodePolicyData(const em::PolicyData& policy_data, | |
| 163 PolicyMap* policies) { | |
| 164 em::ChromeDeviceSettingsProto policy; | |
| 165 if (!policy.ParseFromString(policy_data.policy_value())) { | |
| 166 LOG(WARNING) << "Failed to parse ChromeDeviceSettingsProto."; | |
| 167 return false; | |
| 168 } | |
| 169 DecodeDevicePolicy(policy, policies, install_attributes_); | |
| 170 return true; | |
| 171 } | |
| 172 | |
| 173 void DevicePolicyCache::PolicyStoreOpCompleted() { | |
| 174 DCHECK(CalledOnValidThread()); | |
| 175 chromeos::DeviceSettingsService::Status status = | |
| 176 device_settings_service_->status(); | |
| 177 if (status != chromeos::DeviceSettingsService::STORE_SUCCESS) { | |
| 178 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyStoreFailed, | |
| 179 kMetricPolicySize); | |
| 180 if (status == chromeos::DeviceSettingsService::STORE_VALIDATION_ERROR) { | |
| 181 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchBadSignature, | |
| 182 kMetricPolicySize); | |
| 183 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 184 CloudPolicySubsystem::SIGNATURE_MISMATCH); | |
| 185 } else { | |
| 186 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchOtherFailed, | |
| 187 kMetricPolicySize); | |
| 188 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 189 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
| 190 } | |
| 191 CheckFetchingDone(); | |
| 192 return; | |
| 193 } | |
| 194 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyStoreSucceeded, | |
| 195 kMetricPolicySize); | |
| 196 | |
| 197 CheckFetchingDone(); | |
| 198 } | |
| 199 | |
| 200 void DevicePolicyCache::InstallInitialPolicy( | |
| 201 chromeos::DeviceSettingsService::Status status, | |
| 202 const em::PolicyData* policy_data, | |
| 203 std::string* device_token) { | |
| 204 if (status == chromeos::DeviceSettingsService::STORE_NO_POLICY || | |
| 205 status == chromeos::DeviceSettingsService::STORE_KEY_UNAVAILABLE) { | |
| 206 InformNotifier(CloudPolicySubsystem::UNENROLLED, | |
| 207 CloudPolicySubsystem::NO_DETAILS); | |
| 208 return; | |
| 209 } | |
| 210 if (!policy_data) { | |
| 211 LOG(WARNING) << "Failed to parse PolicyData protobuf."; | |
| 212 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyLoadFailed, | |
| 213 kMetricPolicySize); | |
| 214 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 215 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
| 216 return; | |
| 217 } | |
| 218 if (!policy_data->has_request_token() || | |
| 219 policy_data->request_token().empty()) { | |
| 220 SetUnmanagedInternal(base::Time::NowFromSystemTime()); | |
| 221 InformNotifier(CloudPolicySubsystem::UNMANAGED, | |
| 222 CloudPolicySubsystem::NO_DETAILS); | |
| 223 // TODO(jkummerow): Reminder: When we want to feed device-wide settings | |
| 224 // made by a local owner into this cache, we need to call | |
| 225 // SetPolicyInternal() here. | |
| 226 return; | |
| 227 } | |
| 228 if (!policy_data->has_username() || !policy_data->has_device_id()) { | |
| 229 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyLoadFailed, | |
| 230 kMetricPolicySize); | |
| 231 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 232 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
| 233 return; | |
| 234 } | |
| 235 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyLoadSucceeded, | |
| 236 kMetricPolicySize); | |
| 237 data_store_->set_user_name(policy_data->username()); | |
| 238 data_store_->set_device_id(policy_data->device_id()); | |
| 239 *device_token = policy_data->request_token(); | |
| 240 base::Time timestamp; | |
| 241 em::PolicyFetchResponse policy_response; | |
| 242 CHECK(policy_data->SerializeToString(policy_response.mutable_policy_data())); | |
| 243 if (SetPolicyInternal(policy_response, ×tamp, true)) | |
| 244 set_last_policy_refresh_time(timestamp); | |
| 245 } | |
| 246 | |
| 247 void DevicePolicyCache::SetTokenAndFlagReady(const std::string& device_token) { | |
| 248 // We need to call SetDeviceToken unconditionally to indicate the cache has | |
| 249 // finished loading. | |
| 250 data_store_->SetDeviceToken(device_token, true); | |
| 251 SetReady(); | |
| 252 } | |
| 253 | |
| 254 void DevicePolicyCache::CheckFetchingDone() { | |
| 255 if (policy_fetch_pending_) { | |
| 256 CloudPolicyCacheBase::SetFetchingDone(); | |
| 257 policy_fetch_pending_ = false; | |
| 258 } | |
| 259 } | |
| 260 | |
| 261 } // namespace policy | |
| OLD | NEW |