Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_cache.h" | 5 #include "chrome/browser/policy/cloud_policy_cache.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 // Policy level this provider will handle. | 75 // Policy level this provider will handle. |
| 76 CloudPolicyCache::PolicyLevel level_; | 76 CloudPolicyCache::PolicyLevel level_; |
| 77 | 77 |
| 78 DISALLOW_COPY_AND_ASSIGN(CloudPolicyProvider); | 78 DISALLOW_COPY_AND_ASSIGN(CloudPolicyProvider); |
| 79 }; | 79 }; |
| 80 | 80 |
| 81 // Saves policy information to a file. | 81 // Saves policy information to a file. |
| 82 class PersistPolicyTask : public Task { | 82 class PersistPolicyTask : public Task { |
| 83 public: | 83 public: |
| 84 PersistPolicyTask(const FilePath& path, | 84 PersistPolicyTask(const FilePath& path, |
| 85 const em::CloudPolicyResponse* cloud_policy_response, | 85 const em::PolicyFetchResponse* cloud_policy_response, |
| 86 const em::DevicePolicyResponse* device_policy_response, | 86 const em::DevicePolicyResponse* device_policy_response, |
| 87 const bool is_unmanaged) | 87 const bool is_unmanaged) |
| 88 : path_(path), | 88 : path_(path), |
| 89 cloud_policy_response_(cloud_policy_response), | 89 cloud_policy_response_(cloud_policy_response), |
| 90 device_policy_response_(device_policy_response), | 90 device_policy_response_(device_policy_response), |
| 91 is_unmanaged_(is_unmanaged) {} | 91 is_unmanaged_(is_unmanaged) {} |
| 92 | 92 |
| 93 private: | 93 private: |
| 94 // Task override. | 94 // Task override. |
| 95 virtual void Run(); | 95 virtual void Run(); |
| 96 | 96 |
| 97 const FilePath path_; | 97 const FilePath path_; |
| 98 scoped_ptr<const em::CloudPolicyResponse> cloud_policy_response_; | 98 scoped_ptr<const em::PolicyFetchResponse> cloud_policy_response_; |
| 99 scoped_ptr<const em::DevicePolicyResponse> device_policy_response_; | 99 scoped_ptr<const em::DevicePolicyResponse> device_policy_response_; |
| 100 const bool is_unmanaged_; | 100 const bool is_unmanaged_; |
| 101 }; | 101 }; |
| 102 | 102 |
| 103 void PersistPolicyTask::Run() { | 103 void PersistPolicyTask::Run() { |
| 104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 105 std::string data; | 105 std::string data; |
| 106 em::CachedCloudPolicyResponse cached_policy; | 106 em::CachedCloudPolicyResponse cached_policy; |
| 107 if (cloud_policy_response_.get()) { | 107 if (cloud_policy_response_.get()) { |
| 108 cached_policy.mutable_cloud_policy()->CopyFrom(*cloud_policy_response_); | 108 cached_policy.mutable_cloud_policy()->CopyFrom(*cloud_policy_response_); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 125 return; | 125 return; |
| 126 } | 126 } |
| 127 } | 127 } |
| 128 | 128 |
| 129 CloudPolicyCache::CloudPolicyCache( | 129 CloudPolicyCache::CloudPolicyCache( |
| 130 const FilePath& backing_file_path) | 130 const FilePath& backing_file_path) |
| 131 : backing_file_path_(backing_file_path), | 131 : backing_file_path_(backing_file_path), |
| 132 device_policy_(new DictionaryValue), | 132 device_policy_(new DictionaryValue), |
| 133 initialization_complete_(false), | 133 initialization_complete_(false), |
| 134 is_unmanaged_(false), | 134 is_unmanaged_(false), |
| 135 has_device_policy_(false) { | 135 has_device_policy_(false), |
| 136 last_policy_server_timestamp_(0) { | |
| 136 managed_policy_provider_.reset( | 137 managed_policy_provider_.reset( |
| 137 new CloudPolicyProvider( | 138 new CloudPolicyProvider( |
| 138 ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), | 139 ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), |
| 139 this, | 140 this, |
| 140 POLICY_LEVEL_MANDATORY)); | 141 POLICY_LEVEL_MANDATORY)); |
| 141 recommended_policy_provider_.reset( | 142 recommended_policy_provider_.reset( |
| 142 new CloudPolicyProvider( | 143 new CloudPolicyProvider( |
| 143 ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), | 144 ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), |
| 144 this, | 145 this, |
| 145 POLICY_LEVEL_RECOMMENDED)); | 146 POLICY_LEVEL_RECOMMENDED)); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 165 return; | 166 return; |
| 166 } | 167 } |
| 167 | 168 |
| 168 em::CachedCloudPolicyResponse cached_response; | 169 em::CachedCloudPolicyResponse cached_response; |
| 169 if (!cached_response.ParseFromArray(data.c_str(), data.size())) { | 170 if (!cached_response.ParseFromArray(data.c_str(), data.size())) { |
| 170 LOG(WARNING) << "Failed to parse policy data read from " | 171 LOG(WARNING) << "Failed to parse policy data read from " |
| 171 << backing_file_path_.value(); | 172 << backing_file_path_.value(); |
| 172 return; | 173 return; |
| 173 } | 174 } |
| 174 base::Time timestamp; | 175 base::Time timestamp; |
| 176 int64 raw_timestamp; | |
| 175 PolicyMap mandatory_policy; | 177 PolicyMap mandatory_policy; |
| 176 PolicyMap recommended_policy; | 178 PolicyMap recommended_policy; |
| 177 is_unmanaged_ = cached_response.unmanaged(); | 179 is_unmanaged_ = cached_response.unmanaged(); |
| 178 if (is_unmanaged_ || cached_response.has_device_policy()) | 180 if (is_unmanaged_ || cached_response.has_device_policy()) |
| 179 timestamp = base::Time::FromTimeT(cached_response.timestamp()); | 181 timestamp = base::Time::FromTimeT(cached_response.timestamp()); |
| 180 if (cached_response.has_cloud_policy()) { | 182 if (cached_response.has_cloud_policy()) { |
| 181 DCHECK(!is_unmanaged_); | 183 DCHECK(!is_unmanaged_); |
| 182 bool ok = DecodePolicyResponse(cached_response.cloud_policy(), | 184 bool ok = DecodePolicyResponse(cached_response.cloud_policy(), |
| 183 &mandatory_policy, | 185 &mandatory_policy, |
| 184 &recommended_policy, | 186 &recommended_policy, |
| 185 ×tamp); | 187 ×tamp, |
| 188 &raw_timestamp); | |
| 186 if (!ok) { | 189 if (!ok) { |
| 187 LOG(WARNING) << "Decoding policy data failed."; | 190 LOG(WARNING) << "Decoding policy data failed."; |
| 188 return; | 191 return; |
| 189 } | 192 } |
| 190 } | 193 } |
| 191 if (timestamp > base::Time::NowFromSystemTime()) { | 194 if (timestamp > base::Time::NowFromSystemTime()) { |
| 192 LOG(WARNING) << "Rejected policy data from " << backing_file_path_.value() | 195 LOG(WARNING) << "Rejected policy data from " << backing_file_path_.value() |
| 193 << ", file is from the future."; | 196 << ", file is from the future."; |
| 194 return; | 197 return; |
| 195 } | 198 } |
| 196 // Swap in the new policy information. | 199 // Swap in the new policy information. |
| 197 if (cached_response.has_cloud_policy()) { | 200 if (cached_response.has_cloud_policy()) { |
| 198 mandatory_policy_.Swap(&mandatory_policy); | 201 mandatory_policy_.Swap(&mandatory_policy); |
| 199 recommended_policy_.Swap(&recommended_policy); | 202 recommended_policy_.Swap(&recommended_policy); |
| 203 last_policy_server_timestamp_ = raw_timestamp; | |
| 200 has_device_policy_ = false; | 204 has_device_policy_ = false; |
| 201 } else if (cached_response.has_device_policy()) { | 205 } else if (cached_response.has_device_policy()) { |
| 202 scoped_ptr<DictionaryValue> value( | 206 scoped_ptr<DictionaryValue> value( |
| 203 DecodeDevicePolicy(cached_response.device_policy())); | 207 DecodeDevicePolicy(cached_response.device_policy())); |
| 204 device_policy_.reset(value.release()); | 208 device_policy_.reset(value.release()); |
| 205 has_device_policy_ = true; | 209 has_device_policy_ = true; |
| 206 } | 210 } |
| 207 last_policy_refresh_time_ = timestamp; | 211 last_policy_refresh_time_ = timestamp; |
| 208 initialization_complete_ = true; | 212 initialization_complete_ = true; |
| 209 | 213 |
| 210 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, | 214 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, |
| 211 observer_list_, OnUpdatePolicy()); | 215 observer_list_, OnUpdatePolicy()); |
| 212 } | 216 } |
| 213 | 217 |
| 214 void CloudPolicyCache::SetPolicy(const em::CloudPolicyResponse& policy) { | 218 void CloudPolicyCache::SetPolicy(const em::PolicyFetchResponse& policy) { |
| 215 DCHECK(CalledOnValidThread()); | 219 DCHECK(CalledOnValidThread()); |
| 216 bool initialization_was_not_complete = !initialization_complete_; | 220 bool initialization_was_not_complete = !initialization_complete_; |
| 217 is_unmanaged_ = false; | 221 is_unmanaged_ = false; |
| 218 base::Time timestamp; | 222 base::Time timestamp; |
| 223 int64 raw_timestamp; | |
| 219 PolicyMap mandatory_policy; | 224 PolicyMap mandatory_policy; |
| 220 PolicyMap recommended_policy; | 225 PolicyMap recommended_policy; |
| 221 bool ok = DecodePolicyResponse(policy, &mandatory_policy, &recommended_policy, | 226 bool ok = DecodePolicyResponse(policy, &mandatory_policy, &recommended_policy, |
| 222 ×tamp); | 227 ×tamp, &raw_timestamp); |
| 223 if (!ok) | 228 if (!ok) |
| 224 return; | 229 return; |
| 225 | 230 |
| 226 const bool new_policy_differs = | 231 const bool new_policy_differs = |
| 227 !mandatory_policy_.Equals(mandatory_policy) || | 232 !mandatory_policy_.Equals(mandatory_policy) || |
| 228 !recommended_policy_.Equals(recommended_policy); | 233 !recommended_policy_.Equals(recommended_policy); |
| 229 mandatory_policy_.Swap(&mandatory_policy); | 234 mandatory_policy_.Swap(&mandatory_policy); |
| 230 recommended_policy_.Swap(&recommended_policy); | 235 recommended_policy_.Swap(&recommended_policy); |
| 231 initialization_complete_ = true; | 236 initialization_complete_ = true; |
| 232 last_policy_refresh_time_ = timestamp; | 237 last_policy_refresh_time_ = timestamp; |
| 238 last_policy_server_timestamp_ = raw_timestamp; | |
| 233 has_device_policy_ = false; | 239 has_device_policy_ = false; |
| 234 | 240 |
| 235 if (new_policy_differs || initialization_was_not_complete) { | 241 if (new_policy_differs || initialization_was_not_complete) { |
| 236 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, | 242 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, |
| 237 observer_list_, OnUpdatePolicy()); | 243 observer_list_, OnUpdatePolicy()); |
| 238 } | 244 } |
| 239 | 245 |
| 240 if (timestamp > base::Time::NowFromSystemTime() + | 246 if (timestamp > base::Time::NowFromSystemTime() + |
| 241 base::TimeDelta::FromMinutes(1)) { | 247 base::TimeDelta::FromMinutes(1)) { |
| 242 LOG(WARNING) << "Server returned policy with timestamp from the future, " | 248 LOG(WARNING) << "Server returned policy with timestamp from the future, " |
| 243 "not persisting to disk."; | 249 "not persisting to disk."; |
| 244 } else { | 250 } else { |
| 245 em::CloudPolicyResponse* policy_copy = new em::CloudPolicyResponse; | 251 em::PolicyFetchResponse* policy_copy = new em::PolicyFetchResponse; |
| 246 policy_copy->CopyFrom(policy); | 252 policy_copy->CopyFrom(policy); |
| 247 BrowserThread::PostTask( | 253 BrowserThread::PostTask( |
| 248 BrowserThread::FILE, | 254 BrowserThread::FILE, |
| 249 FROM_HERE, | 255 FROM_HERE, |
| 250 new PersistPolicyTask(backing_file_path_, policy_copy, NULL, false)); | 256 new PersistPolicyTask(backing_file_path_, policy_copy, NULL, false)); |
| 251 } | 257 } |
| 252 } | 258 } |
| 253 | 259 |
| 254 void CloudPolicyCache::SetDevicePolicy(const em::DevicePolicyResponse& policy) { | 260 void CloudPolicyCache::SetDevicePolicy(const em::DevicePolicyResponse& policy) { |
| 255 DCHECK(CalledOnValidThread()); | 261 DCHECK(CalledOnValidThread()); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 298 observer_list_, OnUpdatePolicy()); | 304 observer_list_, OnUpdatePolicy()); |
| 299 | 305 |
| 300 BrowserThread::PostTask( | 306 BrowserThread::PostTask( |
| 301 BrowserThread::FILE, | 307 BrowserThread::FILE, |
| 302 FROM_HERE, | 308 FROM_HERE, |
| 303 new PersistPolicyTask(backing_file_path_, NULL, NULL, true)); | 309 new PersistPolicyTask(backing_file_path_, NULL, NULL, true)); |
| 304 } | 310 } |
| 305 | 311 |
| 306 // static | 312 // static |
| 307 bool CloudPolicyCache::DecodePolicyResponse( | 313 bool CloudPolicyCache::DecodePolicyResponse( |
| 308 const em::CloudPolicyResponse& policy_response, | 314 const em::PolicyFetchResponse& policy_response, |
| 309 PolicyMap* mandatory, | 315 PolicyMap* mandatory, |
| 310 PolicyMap* recommended, | 316 PolicyMap* recommended, |
| 311 base::Time* timestamp) { | 317 base::Time* timestamp, |
| 312 std::string data = policy_response.signed_response(); | 318 int64* raw_timestamp) { |
| 319 std::string data = policy_response.policy_data(); | |
| 313 | 320 |
| 314 if (!VerifySignature(policy_response.signature(), data, | 321 if (!VerifySignature(policy_response.policy_data_signature(), data, |
| 315 policy_response.certificate_chain())) { | 322 policy_response.certificate_chain())) { |
| 316 LOG(WARNING) << "Failed to verify signature."; | 323 LOG(WARNING) << "Failed to verify signature."; |
| 317 return false; | 324 return false; |
| 318 } | 325 } |
| 319 | 326 |
| 320 em::SignedCloudPolicyResponse response; | 327 em::PolicyData policy_data; |
| 321 if (!response.ParseFromArray(data.c_str(), data.size())) { | 328 if (!policy_data.ParseFromString(data)) { |
| 322 LOG(WARNING) << "Failed to parse SignedCloudPolicyResponse protobuf."; | 329 LOG(WARNING) << "Failed to parse PolicyData protobuf."; |
| 323 return false; | 330 return false; |
| 324 } | 331 } |
| 325 | 332 |
| 326 // TODO(jkummerow): Verify response.device_token(). Needs final specification | 333 // TODO(jkummerow): Verify policy_data.device_token(). Needs final |
| 327 // which token we're actually sending / expecting to get back. | 334 // specification which token we're actually sending / expecting to get back. |
| 328 | 335 |
| 329 // TODO(jkummerow): Store response.device_name(), if we decide to transfer | 336 // TODO(jkummerow): Store policy_data.device_name(), if we decide to transfer |
| 330 // it from the server to the client. | 337 // it from the server to the client. |
| 331 | 338 |
| 332 DCHECK(timestamp); | 339 DCHECK(timestamp); |
| 333 *timestamp = base::Time::FromTimeT(response.timestamp()); | 340 DCHECK(raw_timestamp); |
| 334 DecodePolicy(response.settings(), mandatory, recommended); | 341 *raw_timestamp = policy_data.timestamp(); |
| 342 *timestamp = base::Time::UnixEpoch() + | |
| 343 base::TimeDelta::FromMilliseconds(*raw_timestamp); | |
| 344 em::CloudPolicySettings policy; | |
| 345 if (!policy.ParseFromString(policy_data.policy_value())) { | |
| 346 LOG(WARNING) << "Failed to parse CloudPolicySettingsj protobuf."; | |
|
Jakob Kummerow
2011/02/28 11:06:31
nit: j?
gfeher
2011/02/28 12:21:32
Done.
| |
| 347 return false; | |
| 348 } | |
| 349 DecodePolicy(policy, mandatory, recommended); | |
| 335 return true; | 350 return true; |
| 336 } | 351 } |
| 337 | 352 |
| 338 // static | 353 // static |
| 339 bool CloudPolicyCache::VerifySignature( | 354 bool CloudPolicyCache::VerifySignature( |
| 340 const std::string& signature, | 355 const std::string& signature, |
| 341 const std::string& data, | 356 const std::string& data, |
| 342 const RepeatedPtrField<std::string>& certificate_chain) { | 357 const RepeatedPtrField<std::string>& certificate_chain) { |
| 343 // TODO(jkummerow): Implement this. Non-trivial because we want to do it | 358 // TODO(jkummerow): Implement this. Non-trivial because we want to do it |
| 344 // for all platforms -> it's enough work to deserve its own CL. | 359 // for all platforms -> it's enough work to deserve its own CL. |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 CloudPolicyCache::DecodeValue(named_value->value()); | 469 CloudPolicyCache::DecodeValue(named_value->value()); |
| 455 if (decoded_value) | 470 if (decoded_value) |
| 456 result->Set(named_value->name(), decoded_value); | 471 result->Set(named_value->name(), decoded_value); |
| 457 } | 472 } |
| 458 } | 473 } |
| 459 } | 474 } |
| 460 return result; | 475 return result; |
| 461 } | 476 } |
| 462 | 477 |
| 463 } // namespace policy | 478 } // namespace policy |
| OLD | NEW |