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 #ifndef CHROME_BROWSER_POLICY_CLOUD_POLICY_VALIDATOR_H_ | |
6 #define CHROME_BROWSER_POLICY_CLOUD_POLICY_VALIDATOR_H_ | |
7 | |
8 #include <string> | |
9 #include <vector> | |
10 | |
11 #include "base/basictypes.h" | |
12 #include "base/callback.h" | |
13 #include "base/memory/ref_counted.h" | |
14 #include "base/memory/scoped_ptr.h" | |
15 #include "base/time.h" | |
16 | |
17 namespace base { | |
18 class MessageLoopProxy; | |
19 } | |
20 | |
21 namespace google { | |
22 namespace protobuf { | |
23 class MessageLite; | |
24 } | |
25 } | |
26 | |
27 namespace enterprise_management { | |
28 class ChromeDeviceSettingsProto; | |
29 class CloudPolicySettings; | |
30 class PolicyData; | |
31 class PolicyFetchResponse; | |
32 } | |
33 | |
34 namespace policy { | |
35 | |
36 // Helper class that implements the gory details of validating a policy blob. | |
37 // Since signature checks are expensive, validation can happen on the FILE | |
38 // thread. The pattern is to create a validator, configure its behavior through | |
39 // the ValidateXYZ() functions, and then call StartValidation(). Alternatively, | |
40 // RunValidation() can be used to perform validation on the current thread. | |
41 class CloudPolicyValidatorBase { | |
42 public: | |
43 // Validation result codes. | |
44 enum Status { | |
45 // Indicates successful validation. | |
46 VALIDATION_OK, | |
47 // Bad signature. | |
48 VALIDATION_BAD_SIGNATURE, | |
49 // Policy blob contains error code. | |
50 VALIDATION_ERROR_CODE_PRESENT, | |
51 // Policy payload failed to decode. | |
52 VALIDATION_PAYLOAD_PARSE_ERROR, | |
53 // Unexpected policy type. | |
54 VALIDATION_WRONG_POLICY_TYPE, | |
55 // Time stamp from the future. | |
56 VALIDATION_BAD_TIMESTAMP, | |
57 // Token doesn't match. | |
58 VALIDATION_WRONG_TOKEN, | |
59 // Username doesn't match. | |
60 VALIDATION_BAD_USERNAME, | |
61 // Policy payload protobuf parse error. | |
62 VALIDATION_POLICY_PARSE_ERROR, | |
63 }; | |
64 | |
65 virtual ~CloudPolicyValidatorBase(); | |
66 | |
67 // Validation status which can be read after completion has been signaled. | |
68 Status status() const { return status_; } | |
69 bool success() const { return status_ == VALIDATION_OK; } | |
70 | |
71 // The policy objects owned by the validator. These are scoped_ptr | |
72 // references, so ownership can be passed on once validation is complete. | |
73 scoped_ptr<enterprise_management::PolicyFetchResponse>& policy() { | |
74 return policy_; | |
75 } | |
76 scoped_ptr<enterprise_management::PolicyData>& policy_data() { | |
77 return policy_data_; | |
78 } | |
79 | |
80 // Instructs the validator to check that the policy timestamp is not before | |
81 // |not_before| and not after |now| + grace interval. | |
82 void ValidateTimestamp(base::Time not_before, | |
83 base::Time now, | |
84 bool allow_missing_timestamp); | |
85 | |
86 // Validates the username in the policy blob matches |expected_user|. | |
87 void ValidateUsername(const std::string& expected_user); | |
88 | |
89 // Validates the policy blob is addressed to |expected_domain|. This uses the | |
90 // domain part of the username field in the policy for the check. | |
91 void ValidateDomain(const std::string& expected_domain); | |
92 | |
93 // Makes sure the DM token on the policy matches |expected_token|. | |
94 void ValidateDMToken(const std::string& dm_token); | |
95 | |
96 // Validates the policy type. | |
97 void ValidatePolicyType(const std::string& policy_type); | |
98 | |
99 // Validates that the payload can be decoded successfully. | |
100 void ValidatePayload(); | |
101 | |
102 // Verifies that the signature on the policy blob verifies against |key|. If | | |
103 // |allow_key_rotation| is true and there is a key rotation present in the | |
104 // policy blob, this checks the signature on the new key against |key| and the | |
105 // policy blob against the new key. | |
106 void ValidateSignature(const std::vector<uint8>& key, | |
107 bool allow_key_rotation); | |
108 | |
109 // Similar to StartSignatureVerification(), this checks the signature on the | |
110 // policy blob. However, this variant expects a new policy key set in the | |
111 // policy blob and makes sure the policy is signed using that key. This should | |
112 // be called at setup time when there is no existing policy key present to | |
113 // check against. | |
114 void ValidateInitialKey(); | |
115 | |
116 // Convenience helper that configures timestamp and token validation based on | |
117 // the current policy blob. |policy_data| may be NULL, in which case the | |
118 // timestamp validation will drop the lower bound and no token validation will | |
119 // be configured. | |
120 void ValidateAgainstCurrentPolicy( | |
121 const enterprise_management::PolicyData* policy_data, | |
122 bool allow_missing_timestamp); | |
123 | |
124 // Immediately performs validation on the current thread. | |
125 void RunValidation(); | |
126 | |
127 protected: | |
128 // Create a new validator that checks |policy_response|. |payload| is the | |
129 // message that the policy payload will be parsed to, and it needs to stay | |
130 // valid for the lifetime of the validator. | |
131 CloudPolicyValidatorBase( | |
132 scoped_ptr<enterprise_management::PolicyFetchResponse> policy_response, | |
133 google::protobuf::MessageLite* payload); | |
134 | |
135 // Performs validation, called on a background thread. | |
136 static void PerformValidation( | |
137 scoped_ptr<CloudPolicyValidatorBase> self, | |
138 scoped_refptr<base::MessageLoopProxy> message_loop, | |
139 const base::Closure& completion_callback); | |
140 | |
141 private: | |
142 // Internal flags indicating what to check. | |
143 enum ValidationFlags { | |
144 VALIDATE_TIMESTAMP = 1 << 0, | |
145 VALIDATE_USERNAME = 1 << 1, | |
146 VALIDATE_DOMAIN = 1 << 2, | |
147 VALIDATE_TOKEN = 1 << 3, | |
148 VALIDATE_POLICY_TYPE = 1 << 4, | |
149 VALIDATE_PAYLOAD = 1 << 5, | |
150 VALIDATE_SIGNATURE = 1 << 6, | |
151 VALIDATE_INITIAL_KEY = 1 << 7, | |
152 }; | |
153 | |
154 // Reports completion to the |completion_callback_|. | |
155 static void ReportCompletion(scoped_ptr<CloudPolicyValidatorBase> self, | |
156 const base::Closure& completion_callback); | |
157 | |
158 // Invokes all the checks and reports the result. | |
159 void RunChecks(); | |
160 | |
161 // Helper functions implementing individual checks. | |
162 Status CheckTimestamp(); | |
163 Status CheckUsername(); | |
164 Status CheckDomain(); | |
165 Status CheckToken(); | |
166 Status CheckPolicyType(); | |
167 Status CheckPayload(); | |
168 Status CheckSignature(); | |
169 Status CheckInitialKey(); | |
170 | |
171 // Verifies the SHA1/RSA |signature| on |data| against |key|. | |
172 static bool VerifySignature(const std::string& data, | |
173 const std::string& key, | |
174 const std::string& signature); | |
175 | |
176 Status status_; | |
177 scoped_ptr<enterprise_management::PolicyFetchResponse> policy_; | |
178 scoped_ptr<enterprise_management::PolicyData> policy_data_; | |
179 google::protobuf::MessageLite* payload_; | |
180 | |
181 int validation_flags_; | |
182 int64 timestamp_not_before_; | |
183 int64 timestamp_not_after_; | |
184 bool allow_missing_timestamp_; | |
185 std::string user_; | |
186 std::string domain_; | |
187 std::string token_; | |
188 std::string policy_type_; | |
189 std::string key_; | |
190 bool allow_key_rotation_; | |
191 | |
192 DISALLOW_COPY_AND_ASSIGN(CloudPolicyValidatorBase); | |
193 }; | |
194 | |
195 // A simple type-parameterized extension of CloudPolicyValidator that | |
196 // facilitates working with the actual protobuf payload type. | |
197 template<typename PayloadProto> | |
198 class CloudPolicyValidator : public CloudPolicyValidatorBase { | |
199 public: | |
200 typedef base::Callback<void(CloudPolicyValidator<PayloadProto>*)> | |
201 CompletionCallback; | |
202 | |
203 virtual ~CloudPolicyValidator(); | |
204 | |
205 // Creates a new validator. | |
206 static CloudPolicyValidator<PayloadProto>* Create( | |
207 scoped_ptr<enterprise_management::PolicyFetchResponse> policy_response); | |
208 | |
209 scoped_ptr<PayloadProto>& payload() { | |
210 return payload_; | |
211 } | |
212 | |
213 // Kicks off asynchronous validation. |completion_callback| is invoked when | |
214 // done. From this point on, the validator manages its own lifetime - this | |
215 // allows callers to provide a WeakPtr in the callback without leaking the | |
216 // validator. | |
217 void StartValidation(const CompletionCallback& completion_callback); | |
218 | |
219 private: | |
220 CloudPolicyValidator( | |
221 scoped_ptr<enterprise_management::PolicyFetchResponse> policy_response, | |
222 scoped_ptr<PayloadProto> payload); | |
223 | |
224 scoped_ptr<PayloadProto> payload_; | |
225 | |
226 DISALLOW_COPY_AND_ASSIGN(CloudPolicyValidator); | |
227 }; | |
228 | |
229 typedef CloudPolicyValidator<enterprise_management::ChromeDeviceSettingsProto> | |
230 DeviceCloudPolicyValidator; | |
231 typedef CloudPolicyValidator<enterprise_management::CloudPolicySettings> | |
232 UserCloudPolicyValidator; | |
233 | |
234 } // namespace policy | |
235 | |
236 #endif // CHROME_BROWSER_POLICY_CLOUD_POLICY_VALIDATOR_H_ | |
OLD | NEW |