| 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 |