Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(758)

Side by Side Diff: chrome/browser/policy/component_cloud_policy_store.cc

Issue 12189011: Split up chrome/browser/policy subdirectory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, add chrome/browser/chromeos/policy/OWNERS Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 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/component_cloud_policy_store.h"
6
7 #include "base/json/json_reader.h"
8 #include "base/logging.h"
9 #include "base/sha1.h"
10 #include "base/string_util.h"
11 #include "base/values.h"
12 #include "chrome/browser/policy/cloud_policy_constants.h"
13 #include "chrome/browser/policy/cloud_policy_validator.h"
14 #include "chrome/browser/policy/policy_map.h"
15 #include "chrome/browser/policy/proto/chrome_extension_policy.pb.h"
16 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
17 #include "chrome/browser/policy/resource_cache.h"
18 #include "googleurl/src/gurl.h"
19
20 namespace em = enterprise_management;
21
22 namespace policy {
23
24 namespace {
25
26 const char kValue[] = "Value";
27 const char kLevel[] = "Level";
28 const char kMandatory[] = "Mandatory";
29 const char kRecommended[] = "Recommended";
30
31 const struct DomainConstants {
32 PolicyDomain domain;
33 const char* proto_cache_key;
34 const char* data_cache_key;
35 const char* policy_type;
36 } kDomains[] = {
37 {
38 POLICY_DOMAIN_EXTENSIONS,
39 "extension-policy",
40 "extension-policy-data",
41 dm_protocol::kChromeExtensionPolicyType,
42 },
43 };
44
45 const DomainConstants* GetDomainConstants(PolicyDomain domain) {
46 for (size_t i = 0; i < arraysize(kDomains); ++i) {
47 if (kDomains[i].domain == domain)
48 return &kDomains[i];
49 }
50 return NULL;
51 }
52
53 const DomainConstants* GetDomainConstantsForType(const std::string& type) {
54 for (size_t i = 0; i < arraysize(kDomains); ++i) {
55 if (kDomains[i].policy_type == type)
56 return &kDomains[i];
57 }
58 return NULL;
59 }
60
61 } // namespace
62
63 ComponentCloudPolicyStore::Delegate::~Delegate() {}
64
65 ComponentCloudPolicyStore::ComponentCloudPolicyStore(
66 Delegate* delegate,
67 ResourceCache* cache)
68 : delegate_(delegate),
69 cache_(cache) {}
70
71 ComponentCloudPolicyStore::~ComponentCloudPolicyStore() {
72 DCHECK(CalledOnValidThread());
73 }
74
75 // static
76 bool ComponentCloudPolicyStore::SupportsDomain(PolicyDomain domain) {
77 return GetDomainConstants(domain) != NULL;
78 }
79
80 // static
81 bool ComponentCloudPolicyStore::GetPolicyType(PolicyDomain domain,
82 std::string* policy_type) {
83 const DomainConstants* constants = GetDomainConstants(domain);
84 if (constants)
85 *policy_type = constants->policy_type;
86 return constants != NULL;
87 }
88
89 // static
90 bool ComponentCloudPolicyStore::GetPolicyDomain(const std::string& policy_type,
91 PolicyDomain* domain) {
92 const DomainConstants* constants = GetDomainConstantsForType(policy_type);
93 if (constants)
94 *domain = constants->domain;
95 return constants != NULL;
96 }
97
98 const std::string& ComponentCloudPolicyStore::GetCachedHash(
99 const PolicyNamespace& ns) const {
100 DCHECK(CalledOnValidThread());
101 std::map<PolicyNamespace, std::string>::const_iterator it =
102 cached_hashes_.find(ns);
103 return it == cached_hashes_.end() ? EmptyString() : it->second;
104 }
105
106 void ComponentCloudPolicyStore::SetCredentials(const std::string& username,
107 const std::string& dm_token) {
108 DCHECK(CalledOnValidThread());
109 DCHECK(username_.empty() || username == username_);
110 DCHECK(dm_token_.empty() || dm_token == dm_token_);
111 username_ = username;
112 dm_token_ = dm_token;
113 }
114
115 void ComponentCloudPolicyStore::Load() {
116 DCHECK(CalledOnValidThread());
117 typedef std::map<std::string, std::string> ContentMap;
118
119 // Load all cached policy protobufs for each domain.
120 for (size_t domain = 0; domain < arraysize(kDomains); ++domain) {
121 const DomainConstants& constants = kDomains[domain];
122 ContentMap protos;
123 cache_->LoadAllSubkeys(constants.proto_cache_key, &protos);
124 for (ContentMap::iterator it = protos.begin(); it != protos.end(); ++it) {
125 const std::string& id(it->first);
126 PolicyNamespace ns(constants.domain, id);
127
128 // Validate each protobuf.
129 scoped_ptr<em::PolicyFetchResponse> proto(new em::PolicyFetchResponse);
130 em::ExternalPolicyData payload;
131 if (!proto->ParseFromString(it->second) ||
132 !ValidateProto(
133 proto.Pass(), constants.policy_type, id, &payload, NULL)) {
134 Delete(ns);
135 continue;
136 }
137
138 // The protobuf looks good; load the policy data.
139 std::string data;
140 PolicyMap policy;
141 if (cache_->Load(constants.data_cache_key, id, &data) &&
142 ValidateData(data, payload.secure_hash(), &policy)) {
143 // The data is also good; expose the policies.
144 policy_bundle_.Get(ns).Swap(&policy);
145 cached_hashes_[ns] = payload.secure_hash();
146 } else {
147 // The data for this proto couldn't be loaded or is corrupted.
148 Delete(ns);
149 }
150 }
151 }
152 }
153
154 bool ComponentCloudPolicyStore::Store(const PolicyNamespace& ns,
155 const std::string& serialized_policy,
156 const std::string& secure_hash,
157 const std::string& data) {
158 DCHECK(CalledOnValidThread());
159 const DomainConstants* constants = GetDomainConstants(ns.domain);
160 PolicyMap policy;
161 // |serialized_policy| has already been validated; validate the data now.
162 if (!constants || !ValidateData(data, secure_hash, &policy))
163 return false;
164
165 // Flush the proto and the data to the cache.
166 cache_->Store(constants->proto_cache_key, ns.component_id, serialized_policy);
167 cache_->Store(constants->data_cache_key, ns.component_id, data);
168 // And expose the policy.
169 policy_bundle_.Get(ns).Swap(&policy);
170 cached_hashes_[ns] = secure_hash;
171 delegate_->OnComponentCloudPolicyStoreUpdated();
172 return true;
173 }
174
175 void ComponentCloudPolicyStore::Delete(const PolicyNamespace& ns) {
176 DCHECK(CalledOnValidThread());
177 const DomainConstants* constants = GetDomainConstants(ns.domain);
178 if (!constants)
179 return;
180
181 cache_->Delete(constants->proto_cache_key, ns.component_id);
182 cache_->Delete(constants->data_cache_key, ns.component_id);
183
184 if (!policy_bundle_.Get(ns).empty()) {
185 policy_bundle_.Get(ns).Clear();
186 delegate_->OnComponentCloudPolicyStoreUpdated();
187 }
188 }
189
190 void ComponentCloudPolicyStore::Purge(PolicyDomain domain,
191 const std::set<std::string>& keep) {
192 DCHECK(CalledOnValidThread());
193 const DomainConstants* constants = GetDomainConstants(domain);
194 if (!constants)
195 return;
196
197 cache_->PurgeOtherSubkeys(constants->proto_cache_key, keep);
198 cache_->PurgeOtherSubkeys(constants->data_cache_key, keep);
199
200 // Stop serving policies for purged namespaces.
201 bool purged_current_policies = false;
202 for (PolicyBundle::const_iterator it = policy_bundle_.begin();
203 it != policy_bundle_.end(); ++it) {
204 if (it->first.domain == domain &&
205 keep.find(it->first.component_id) == keep.end() &&
206 !policy_bundle_.Get(it->first).empty()) {
207 policy_bundle_.Get(it->first).Clear();
208 purged_current_policies = true;
209 }
210 }
211
212 // Purge cached hashes, so that those namespaces can be fetched again if the
213 // policy state changes.
214 std::map<PolicyNamespace, std::string>::iterator it = cached_hashes_.begin();
215 while (it != cached_hashes_.end()) {
216 if (it->first.domain == domain &&
217 keep.find(it->first.component_id) == keep.end()) {
218 std::map<PolicyNamespace, std::string>::iterator prev = it;
219 ++it;
220 cached_hashes_.erase(prev);
221 } else {
222 ++it;
223 }
224 }
225
226 if (purged_current_policies)
227 delegate_->OnComponentCloudPolicyStoreUpdated();
228 }
229
230 bool ComponentCloudPolicyStore::ValidatePolicy(
231 scoped_ptr<em::PolicyFetchResponse> proto,
232 PolicyNamespace* ns,
233 em::ExternalPolicyData* payload) {
234 em::PolicyData policy_data;
235 if (!ValidateProto(
236 proto.Pass(), std::string(), std::string(), payload, &policy_data)) {
237 return false;
238 }
239
240 if (!policy_data.has_policy_type())
241 return false;
242
243 const DomainConstants* constants =
244 GetDomainConstantsForType(policy_data.policy_type());
245 if (!constants || !policy_data.has_settings_entity_id())
246 return false;
247
248 ns->domain = constants->domain;
249 ns->component_id = policy_data.settings_entity_id();
250 return true;
251 }
252
253 bool ComponentCloudPolicyStore::ValidateProto(
254 scoped_ptr<em::PolicyFetchResponse> proto,
255 const std::string& policy_type,
256 const std::string& settings_entity_id,
257 em::ExternalPolicyData* payload,
258 em::PolicyData* policy_data) {
259 if (username_.empty() || dm_token_.empty())
260 return false;
261
262 scoped_ptr<ComponentCloudPolicyValidator> validator(
263 ComponentCloudPolicyValidator::Create(proto.Pass()));
264 validator->ValidateUsername(username_);
265 validator->ValidateDMToken(dm_token_,
266 ComponentCloudPolicyValidator::DM_TOKEN_REQUIRED);
267 if (!policy_type.empty())
268 validator->ValidatePolicyType(policy_type);
269 if (!settings_entity_id.empty())
270 validator->ValidateSettingsEntityId(settings_entity_id);
271 validator->ValidatePayload();
272 // TODO(joaodasilva): validate signature.
273 validator->RunValidation();
274 if (!validator->success())
275 return false;
276
277 em::ExternalPolicyData* data = validator->payload().get();
278 // The download URL must be empty, or must be a valid URL.
279 // An empty download URL signals that this component doesn't have cloud
280 // policy, or that the policy has been removed.
281 if (data->has_download_url() && !data->download_url().empty()) {
282 if (!GURL(data->download_url()).is_valid() ||
283 !data->has_secure_hash() ||
284 data->secure_hash().empty()) {
285 return false;
286 }
287 } else if (data->has_secure_hash()) {
288 return false;
289 }
290
291 if (payload)
292 payload->Swap(validator->payload().get());
293 if (policy_data)
294 policy_data->Swap(validator->policy_data().get());
295 return true;
296 }
297
298 bool ComponentCloudPolicyStore::ValidateData(
299 const std::string& data,
300 const std::string& secure_hash,
301 PolicyMap* policy) {
302 return base::SHA1HashString(data) == secure_hash && ParsePolicy(data, policy);
303 }
304
305 bool ComponentCloudPolicyStore::ParsePolicy(const std::string& data,
306 PolicyMap* policy) {
307 scoped_ptr<base::Value> json(base::JSONReader::Read(
308 data, base::JSON_PARSE_RFC | base::JSON_DETACHABLE_CHILDREN));
309 base::DictionaryValue* dict = NULL;
310 if (!json || !json->GetAsDictionary(&dict))
311 return false;
312
313 // Each top-level key maps a policy name to its description.
314 //
315 // Each description is an object that contains the policy value under the
316 // "Value" key. The optional "Level" key is either "Mandatory" (default) or
317 // "Recommended".
318 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
319 base::DictionaryValue* description = NULL;
320 if (!dict->GetDictionaryWithoutPathExpansion(it.key(), &description))
321 return false;
322
323 base::Value* value = NULL;
324 if (!description->RemoveWithoutPathExpansion(kValue, &value))
325 return false;
326
327 PolicyLevel level = POLICY_LEVEL_MANDATORY;
328 std::string level_string;
329 if (description->GetStringWithoutPathExpansion(kLevel, &level_string) &&
330 level_string == kRecommended) {
331 level = POLICY_LEVEL_RECOMMENDED;
332 }
333
334 // If policy for components is ever used for device-level settings then
335 // this must support a configurable scope; assuming POLICY_SCOPE_USER is
336 // fine for now.
337 policy->Set(it.key(), level, POLICY_SCOPE_USER, value);
338 }
339
340 return true;
341 }
342
343 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/component_cloud_policy_store.h ('k') | chrome/browser/policy/component_cloud_policy_store_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698