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 |