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

Side by Side Diff: chrome/browser/policy/cloud/cloud_policy_validator.h

Issue 109743002: Move policy code into components/policy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: moar fixes Created 7 years 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) 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 #ifndef CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_VALIDATOR_H_
6 #define CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_VALIDATOR_H_
7
8 #include <string>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/sequenced_task_runner.h"
17 #include "base/time/time.h"
18 #include "chrome/browser/policy/proto/cloud/chrome_extension_policy.pb.h"
19 #include "policy/proto/cloud_policy.pb.h"
20
21 namespace base {
22 class MessageLoopProxy;
23 }
24
25 namespace google {
26 namespace protobuf {
27 class MessageLite;
28 }
29 }
30
31 namespace enterprise_management {
32 class PolicyData;
33 class PolicyFetchResponse;
34 }
35
36 namespace policy {
37
38 // Helper class that implements the gory details of validating a policy blob.
39 // Since signature checks are expensive, validation can happen on a background
40 // thread. The pattern is to create a validator, configure its behavior through
41 // the ValidateXYZ() functions, and then call StartValidation(). Alternatively,
42 // RunValidation() can be used to perform validation on the current thread.
43 class CloudPolicyValidatorBase {
44 public:
45 // Validation result codes. These values are also used for UMA histograms;
46 // they must stay stable, and the UMA counters must be updated if new elements
47 // are appended at the end.
48 enum Status {
49 // Indicates successful validation.
50 VALIDATION_OK,
51 // Bad signature on the initial key.
52 VALIDATION_BAD_INITIAL_SIGNATURE,
53 // Bad signature.
54 VALIDATION_BAD_SIGNATURE,
55 // Policy blob contains error code.
56 VALIDATION_ERROR_CODE_PRESENT,
57 // Policy payload failed to decode.
58 VALIDATION_PAYLOAD_PARSE_ERROR,
59 // Unexpected policy type.
60 VALIDATION_WRONG_POLICY_TYPE,
61 // Unexpected settings entity id.
62 VALIDATION_WRONG_SETTINGS_ENTITY_ID,
63 // Time stamp from the future.
64 VALIDATION_BAD_TIMESTAMP,
65 // Token doesn't match.
66 VALIDATION_WRONG_TOKEN,
67 // Username doesn't match.
68 VALIDATION_BAD_USERNAME,
69 // Policy payload protobuf parse error.
70 VALIDATION_POLICY_PARSE_ERROR,
71 };
72
73 enum ValidateDMTokenOption {
74 // The policy must have a non-empty DMToken.
75 DM_TOKEN_REQUIRED,
76
77 // The policy may have an empty or missing DMToken, if the expected token
78 // is also empty.
79 DM_TOKEN_NOT_REQUIRED,
80 };
81
82 enum ValidateTimestampOption {
83 // The policy must have a timestamp field and it should be checked against
84 // both the start and end times.
85 TIMESTAMP_REQUIRED,
86
87 // The timestamp should only be compared vs the |not_before| value (this
88 // is appropriate for platforms with unreliable system times, where we want
89 // to ensure that fresh policy is newer than existing policy, but we can't
90 // do any other validation).
91 TIMESTAMP_NOT_BEFORE,
92
93 // No timestamp field is required.
94 TIMESTAMP_NOT_REQUIRED,
95 };
96
97 virtual ~CloudPolicyValidatorBase();
98
99 // Validation status which can be read after completion has been signaled.
100 Status status() const { return status_; }
101 bool success() const { return status_ == VALIDATION_OK; }
102
103 // The policy objects owned by the validator. These are scoped_ptr
104 // references, so ownership can be passed on once validation is complete.
105 scoped_ptr<enterprise_management::PolicyFetchResponse>& policy() {
106 return policy_;
107 }
108 scoped_ptr<enterprise_management::PolicyData>& policy_data() {
109 return policy_data_;
110 }
111
112 // Instructs the validator to check that the policy timestamp is not before
113 // |not_before| and not after |not_after| + grace interval. If
114 // |timestamp_option| is set to TIMESTAMP_REQUIRED, then the policy will fail
115 // validation if it does not have a timestamp field.
116 void ValidateTimestamp(base::Time not_before,
117 base::Time not_after,
118 ValidateTimestampOption timestamp_option);
119
120 // Validates the username in the policy blob matches |expected_user|.
121 void ValidateUsername(const std::string& expected_user);
122
123 // Validates the policy blob is addressed to |expected_domain|. This uses the
124 // domain part of the username field in the policy for the check.
125 void ValidateDomain(const std::string& expected_domain);
126
127 // Makes sure the DM token on the policy matches |expected_token|.
128 // If |dm_token_option| is DM_TOKEN_REQUIRED, then the policy will fail
129 // validation if it does not have a non-empty request_token field.
130 void ValidateDMToken(const std::string& dm_token,
131 ValidateDMTokenOption dm_token_option);
132
133 // Validates the policy type.
134 void ValidatePolicyType(const std::string& policy_type);
135
136 // Validates the settings_entity_id value.
137 void ValidateSettingsEntityId(const std::string& settings_entity_id);
138
139 // Validates that the payload can be decoded successfully.
140 void ValidatePayload();
141
142 // Verifies that the signature on the policy blob verifies against |key|. If |
143 // |allow_key_rotation| is true and there is a key rotation present in the
144 // policy blob, this checks the signature on the new key against |key| and the
145 // policy blob against the new key.
146 void ValidateSignature(const std::vector<uint8>& key,
147 bool allow_key_rotation);
148
149 // Similar to StartSignatureVerification(), this checks the signature on the
150 // policy blob. However, this variant expects a new policy key set in the
151 // policy blob and makes sure the policy is signed using that key. This should
152 // be called at setup time when there is no existing policy key present to
153 // check against.
154 void ValidateInitialKey();
155
156 // Convenience helper that configures timestamp and token validation based on
157 // the current policy blob. |policy_data| may be NULL, in which case the
158 // timestamp validation will drop the lower bound. |dm_token_option|
159 // and |timestamp_option| have the same effect as the corresponding
160 // parameters for ValidateTimestamp() and ValidateDMToken().
161 void ValidateAgainstCurrentPolicy(
162 const enterprise_management::PolicyData* policy_data,
163 ValidateTimestampOption timestamp_option,
164 ValidateDMTokenOption dm_token_option);
165
166 // Immediately performs validation on the current thread.
167 void RunValidation();
168
169 protected:
170 // Create a new validator that checks |policy_response|. |payload| is the
171 // message that the policy payload will be parsed to, and it needs to stay
172 // valid for the lifetime of the validator.
173 CloudPolicyValidatorBase(
174 scoped_ptr<enterprise_management::PolicyFetchResponse> policy_response,
175 google::protobuf::MessageLite* payload,
176 scoped_refptr<base::SequencedTaskRunner> background_task_runner);
177
178 // Posts an asynchronous calls to PerformValidation, which will eventually
179 // report its result via |completion_callback|.
180 void PostValidationTask(const base::Closure& completion_callback);
181
182 private:
183 // Internal flags indicating what to check.
184 enum ValidationFlags {
185 VALIDATE_TIMESTAMP = 1 << 0,
186 VALIDATE_USERNAME = 1 << 1,
187 VALIDATE_DOMAIN = 1 << 2,
188 VALIDATE_TOKEN = 1 << 3,
189 VALIDATE_POLICY_TYPE = 1 << 4,
190 VALIDATE_ENTITY_ID = 1 << 5,
191 VALIDATE_PAYLOAD = 1 << 6,
192 VALIDATE_SIGNATURE = 1 << 7,
193 VALIDATE_INITIAL_KEY = 1 << 8,
194 };
195
196 // Performs validation, called on a background thread.
197 static void PerformValidation(
198 scoped_ptr<CloudPolicyValidatorBase> self,
199 scoped_refptr<base::MessageLoopProxy> message_loop,
200 const base::Closure& completion_callback);
201
202 // Reports completion to the |completion_callback_|.
203 static void ReportCompletion(scoped_ptr<CloudPolicyValidatorBase> self,
204 const base::Closure& completion_callback);
205
206 // Invokes all the checks and reports the result.
207 void RunChecks();
208
209 // Helper functions implementing individual checks.
210 Status CheckTimestamp();
211 Status CheckUsername();
212 Status CheckDomain();
213 Status CheckToken();
214 Status CheckPolicyType();
215 Status CheckEntityId();
216 Status CheckPayload();
217 Status CheckSignature();
218 Status CheckInitialKey();
219
220 // Verifies the SHA1/RSA |signature| on |data| against |key|.
221 static bool VerifySignature(const std::string& data,
222 const std::string& key,
223 const std::string& signature);
224
225 Status status_;
226 scoped_ptr<enterprise_management::PolicyFetchResponse> policy_;
227 scoped_ptr<enterprise_management::PolicyData> policy_data_;
228 google::protobuf::MessageLite* payload_;
229
230 int validation_flags_;
231 int64 timestamp_not_before_;
232 int64 timestamp_not_after_;
233 ValidateTimestampOption timestamp_option_;
234 ValidateDMTokenOption dm_token_option_;
235 std::string user_;
236 std::string domain_;
237 std::string token_;
238 std::string policy_type_;
239 std::string settings_entity_id_;
240 std::string key_;
241 bool allow_key_rotation_;
242 scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
243
244 DISALLOW_COPY_AND_ASSIGN(CloudPolicyValidatorBase);
245 };
246
247 // A simple type-parameterized extension of CloudPolicyValidator that
248 // facilitates working with the actual protobuf payload type.
249 template<typename PayloadProto>
250 class CloudPolicyValidator : public CloudPolicyValidatorBase {
251 public:
252 typedef base::Callback<void(CloudPolicyValidator<PayloadProto>*)>
253 CompletionCallback;
254
255 virtual ~CloudPolicyValidator() {}
256
257 // Creates a new validator.
258 // |background_task_runner| is optional; if RunValidation() is used directly
259 // and StartValidation() is not used then it can be NULL.
260 static CloudPolicyValidator<PayloadProto>* Create(
261 scoped_ptr<enterprise_management::PolicyFetchResponse> policy_response,
262 scoped_refptr<base::SequencedTaskRunner> background_task_runner) {
263 return new CloudPolicyValidator(
264 policy_response.Pass(),
265 scoped_ptr<PayloadProto>(new PayloadProto()),
266 background_task_runner);
267 }
268
269 scoped_ptr<PayloadProto>& payload() {
270 return payload_;
271 }
272
273 // Kicks off asynchronous validation. |completion_callback| is invoked when
274 // done. From this point on, the validator manages its own lifetime - this
275 // allows callers to provide a WeakPtr in the callback without leaking the
276 // validator.
277 void StartValidation(const CompletionCallback& completion_callback) {
278 PostValidationTask(base::Bind(completion_callback, this));
279 }
280
281 private:
282 CloudPolicyValidator(
283 scoped_ptr<enterprise_management::PolicyFetchResponse> policy_response,
284 scoped_ptr<PayloadProto> payload,
285 scoped_refptr<base::SequencedTaskRunner> background_task_runner)
286 : CloudPolicyValidatorBase(policy_response.Pass(),
287 payload.get(),
288 background_task_runner),
289 payload_(payload.Pass()) {}
290
291 scoped_ptr<PayloadProto> payload_;
292
293 DISALLOW_COPY_AND_ASSIGN(CloudPolicyValidator);
294 };
295
296 typedef CloudPolicyValidator<enterprise_management::CloudPolicySettings>
297 UserCloudPolicyValidator;
298 typedef CloudPolicyValidator<enterprise_management::ExternalPolicyData>
299 ComponentCloudPolicyValidator;
300
301 } // namespace policy
302
303 #endif // CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_VALIDATOR_H_
OLDNEW
« no previous file with comments | « chrome/browser/policy/cloud/cloud_policy_store.cc ('k') | chrome/browser/policy/cloud/cloud_policy_validator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698