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

Unified Diff: chrome/browser/policy/cloud/cloud_policy_validator.cc

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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/policy/cloud/cloud_policy_validator.cc
diff --git a/chrome/browser/policy/cloud/cloud_policy_validator.cc b/chrome/browser/policy/cloud/cloud_policy_validator.cc
deleted file mode 100644
index 8e148e2dc2af6acdf8b82f076ebda4f7e49bd19f..0000000000000000000000000000000000000000
--- a/chrome/browser/policy/cloud/cloud_policy_validator.cc
+++ /dev/null
@@ -1,382 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/policy/cloud/cloud_policy_validator.h"
-
-#include "base/bind_helpers.h"
-#include "base/message_loop/message_loop.h"
-#include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
-#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
-#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
-#include "crypto/signature_verifier.h"
-#include "google_apis/gaia/gaia_auth_util.h"
-
-namespace em = enterprise_management;
-
-namespace policy {
-
-namespace {
-
-// Grace interval for policy timestamp checks, in seconds.
-const int kTimestampGraceIntervalSeconds = 60;
-
-// DER-encoded ASN.1 object identifier for the SHA1-RSA signature algorithm.
-const uint8 kSignatureAlgorithm[] = {
- 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
- 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00
-};
-
-} // namespace
-
-CloudPolicyValidatorBase::~CloudPolicyValidatorBase() {}
-
-void CloudPolicyValidatorBase::ValidateTimestamp(
- base::Time not_before,
- base::Time now,
- ValidateTimestampOption timestamp_option) {
- // Timestamp should be from the past. We allow for a 1-minute grace interval
- // to cover clock drift.
- validation_flags_ |= VALIDATE_TIMESTAMP;
- timestamp_not_before_ =
- (not_before - base::Time::UnixEpoch()).InMilliseconds();
- timestamp_not_after_ =
- ((now + base::TimeDelta::FromSeconds(kTimestampGraceIntervalSeconds)) -
- base::Time::UnixEpoch()).InMillisecondsRoundedUp();
- timestamp_option_ = timestamp_option;
-}
-
-void CloudPolicyValidatorBase::ValidateUsername(
- const std::string& expected_user) {
- validation_flags_ |= VALIDATE_USERNAME;
- user_ = gaia::CanonicalizeEmail(expected_user);
-}
-
-void CloudPolicyValidatorBase::ValidateDomain(
- const std::string& expected_domain) {
- validation_flags_ |= VALIDATE_DOMAIN;
- domain_ = gaia::CanonicalizeDomain(expected_domain);
-}
-
-void CloudPolicyValidatorBase::ValidateDMToken(
- const std::string& token,
- ValidateDMTokenOption dm_token_option) {
- validation_flags_ |= VALIDATE_TOKEN;
- token_ = token;
- dm_token_option_ = dm_token_option;
-}
-
-void CloudPolicyValidatorBase::ValidatePolicyType(
- const std::string& policy_type) {
- validation_flags_ |= VALIDATE_POLICY_TYPE;
- policy_type_ = policy_type;
-}
-
-void CloudPolicyValidatorBase::ValidateSettingsEntityId(
- const std::string& settings_entity_id) {
- validation_flags_ |= VALIDATE_ENTITY_ID;
- settings_entity_id_ = settings_entity_id;
-}
-
-void CloudPolicyValidatorBase::ValidatePayload() {
- validation_flags_ |= VALIDATE_PAYLOAD;
-}
-
-void CloudPolicyValidatorBase::ValidateSignature(const std::vector<uint8>& key,
- bool allow_key_rotation) {
- validation_flags_ |= VALIDATE_SIGNATURE;
- key_ = std::string(reinterpret_cast<const char*>(vector_as_array(&key)),
- key.size());
- allow_key_rotation_ = allow_key_rotation;
-}
-
-void CloudPolicyValidatorBase::ValidateInitialKey() {
- validation_flags_ |= VALIDATE_INITIAL_KEY;
-}
-
-void CloudPolicyValidatorBase::ValidateAgainstCurrentPolicy(
- const em::PolicyData* policy_data,
- ValidateTimestampOption timestamp_option,
- ValidateDMTokenOption dm_token_option) {
- base::Time last_policy_timestamp;
- std::string expected_dm_token;
- if (policy_data) {
- last_policy_timestamp =
- base::Time::UnixEpoch() +
- base::TimeDelta::FromMilliseconds(policy_data->timestamp());
- expected_dm_token = policy_data->request_token();
- }
- ValidateTimestamp(last_policy_timestamp, base::Time::NowFromSystemTime(),
- timestamp_option);
- ValidateDMToken(expected_dm_token, dm_token_option);
-}
-
-CloudPolicyValidatorBase::CloudPolicyValidatorBase(
- scoped_ptr<em::PolicyFetchResponse> policy_response,
- google::protobuf::MessageLite* payload,
- scoped_refptr<base::SequencedTaskRunner> background_task_runner)
- : status_(VALIDATION_OK),
- policy_(policy_response.Pass()),
- payload_(payload),
- validation_flags_(0),
- timestamp_not_before_(0),
- timestamp_not_after_(0),
- timestamp_option_(TIMESTAMP_REQUIRED),
- dm_token_option_(DM_TOKEN_REQUIRED),
- allow_key_rotation_(false),
- background_task_runner_(background_task_runner) {}
-
-void CloudPolicyValidatorBase::PostValidationTask(
- const base::Closure& completion_callback) {
- background_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&CloudPolicyValidatorBase::PerformValidation,
- base::Passed(scoped_ptr<CloudPolicyValidatorBase>(this)),
- base::MessageLoop::current()->message_loop_proxy(),
- completion_callback));
-}
-
-// static
-void CloudPolicyValidatorBase::PerformValidation(
- scoped_ptr<CloudPolicyValidatorBase> self,
- scoped_refptr<base::MessageLoopProxy> message_loop,
- const base::Closure& completion_callback) {
- // Run the validation activities on this thread.
- self->RunValidation();
-
- // Report completion on |message_loop|.
- message_loop->PostTask(
- FROM_HERE,
- base::Bind(&CloudPolicyValidatorBase::ReportCompletion,
- base::Passed(&self),
- completion_callback));
-}
-
-// static
-void CloudPolicyValidatorBase::ReportCompletion(
- scoped_ptr<CloudPolicyValidatorBase> self,
- const base::Closure& completion_callback) {
- completion_callback.Run();
-}
-
-void CloudPolicyValidatorBase::RunValidation() {
- policy_data_.reset(new em::PolicyData());
- RunChecks();
-}
-
-void CloudPolicyValidatorBase::RunChecks() {
- status_ = VALIDATION_OK;
- if ((policy_->has_error_code() && policy_->error_code() != 200) ||
- (policy_->has_error_message() && !policy_->error_message().empty())) {
- LOG(ERROR) << "Error in policy blob."
- << " code: " << policy_->error_code()
- << " message: " << policy_->error_message();
- status_ = VALIDATION_ERROR_CODE_PRESENT;
- return;
- }
-
- // Parse policy data.
- if (!policy_data_->ParseFromString(policy_->policy_data()) ||
- !policy_data_->IsInitialized()) {
- LOG(ERROR) << "Failed to parse policy response";
- status_ = VALIDATION_PAYLOAD_PARSE_ERROR;
- return;
- }
-
- // Table of checks we run. These are sorted by descending severity of the
- // error, s.t. the most severe check will determine the validation status.
- static const struct {
- int flag;
- Status (CloudPolicyValidatorBase::* checkFunction)();
- } kCheckFunctions[] = {
- { VALIDATE_SIGNATURE, &CloudPolicyValidatorBase::CheckSignature },
- { VALIDATE_INITIAL_KEY, &CloudPolicyValidatorBase::CheckInitialKey },
- { VALIDATE_POLICY_TYPE, &CloudPolicyValidatorBase::CheckPolicyType },
- { VALIDATE_ENTITY_ID, &CloudPolicyValidatorBase::CheckEntityId },
- { VALIDATE_TOKEN, &CloudPolicyValidatorBase::CheckToken },
- { VALIDATE_USERNAME, &CloudPolicyValidatorBase::CheckUsername },
- { VALIDATE_DOMAIN, &CloudPolicyValidatorBase::CheckDomain },
- { VALIDATE_TIMESTAMP, &CloudPolicyValidatorBase::CheckTimestamp },
- { VALIDATE_PAYLOAD, &CloudPolicyValidatorBase::CheckPayload },
- };
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kCheckFunctions); ++i) {
- if (validation_flags_ & kCheckFunctions[i].flag) {
- status_ = (this->*(kCheckFunctions[i].checkFunction))();
- if (status_ != VALIDATION_OK)
- break;
- }
- }
-}
-
-CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckSignature() {
- const std::string* signature_key = &key_;
- if (policy_->has_new_public_key() && allow_key_rotation_) {
- signature_key = &policy_->new_public_key();
- if (!policy_->has_new_public_key_signature() ||
- !VerifySignature(policy_->new_public_key(), key_,
- policy_->new_public_key_signature())) {
- LOG(ERROR) << "New public key signature verification failed";
- return VALIDATION_BAD_SIGNATURE;
- }
- }
-
- if (!policy_->has_policy_data_signature() ||
- !VerifySignature(policy_->policy_data(), *signature_key,
- policy_->policy_data_signature())) {
- LOG(ERROR) << "Policy signature validation failed";
- return VALIDATION_BAD_SIGNATURE;
- }
-
- return VALIDATION_OK;
-}
-
-CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckInitialKey() {
- if (!policy_->has_new_public_key() ||
- !policy_->has_policy_data_signature() ||
- !VerifySignature(policy_->policy_data(), policy_->new_public_key(),
- policy_->policy_data_signature())) {
- LOG(ERROR) << "Initial policy signature validation failed";
- return VALIDATION_BAD_INITIAL_SIGNATURE;
- }
-
- return VALIDATION_OK;
-}
-
-CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckPolicyType() {
- if (!policy_data_->has_policy_type() ||
- policy_data_->policy_type() != policy_type_) {
- LOG(ERROR) << "Wrong policy type " << policy_data_->policy_type();
- return VALIDATION_WRONG_POLICY_TYPE;
- }
-
- return VALIDATION_OK;
-}
-
-CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckEntityId() {
- if (!policy_data_->has_settings_entity_id() ||
- policy_data_->settings_entity_id() != settings_entity_id_) {
- LOG(ERROR) << "Wrong settings_entity_id "
- << policy_data_->settings_entity_id() << ", expected "
- << settings_entity_id_;
- return VALIDATION_WRONG_SETTINGS_ENTITY_ID;
- }
-
- return VALIDATION_OK;
-}
-
-CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckTimestamp() {
- if (!policy_data_->has_timestamp()) {
- if (timestamp_option_ == TIMESTAMP_NOT_REQUIRED) {
- return VALIDATION_OK;
- } else {
- LOG(ERROR) << "Policy timestamp missing";
- return VALIDATION_BAD_TIMESTAMP;
- }
- }
-
- if (timestamp_option_ != TIMESTAMP_NOT_REQUIRED &&
- policy_data_->timestamp() < timestamp_not_before_) {
- // If |timestamp_option_| is TIMESTAMP_REQUIRED or TIMESTAMP_NOT_BEFORE
- // then this is a failure.
- LOG(ERROR) << "Policy too old: " << policy_data_->timestamp();
- return VALIDATION_BAD_TIMESTAMP;
- }
- if (timestamp_option_ == TIMESTAMP_REQUIRED &&
- policy_data_->timestamp() > timestamp_not_after_) {
- LOG(ERROR) << "Policy from the future: " << policy_data_->timestamp();
- return VALIDATION_BAD_TIMESTAMP;
- }
-
- return VALIDATION_OK;
-}
-
-CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckToken() {
- // Make sure the token matches the expected token (if any) and also
- // make sure the token itself is valid (non-empty if DM_TOKEN_REQUIRED).
- if (dm_token_option_ == DM_TOKEN_REQUIRED &&
- (!policy_data_->has_request_token() ||
- policy_data_->request_token().empty())) {
- LOG(ERROR) << "Empty DM token encountered - expected: " << token_;
- return VALIDATION_WRONG_TOKEN;
- }
- if (!token_.empty() && policy_data_->request_token() != token_) {
- LOG(ERROR) << "Invalid DM token: " << policy_data_->request_token()
- << " - expected: " << token_;
- return VALIDATION_WRONG_TOKEN;
- }
-
- return VALIDATION_OK;
-}
-
-CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckUsername() {
- if (!policy_data_->has_username()) {
- LOG(ERROR) << "Policy is missing user name";
- return VALIDATION_BAD_USERNAME;
- }
-
- std::string policy_username =
- gaia::CanonicalizeEmail(gaia::SanitizeEmail(policy_data_->username()));
-
- if (user_ != policy_username) {
- LOG(ERROR) << "Invalid user name " << policy_data_->username();
- return VALIDATION_BAD_USERNAME;
- }
-
- return VALIDATION_OK;
-}
-
-
-CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckDomain() {
- if (!policy_data_->has_username()) {
- LOG(ERROR) << "Policy is missing user name";
- return VALIDATION_BAD_USERNAME;
- }
-
- std::string policy_domain =
- gaia::ExtractDomainName(
- gaia::CanonicalizeEmail(
- gaia::SanitizeEmail(policy_data_->username())));
-
- if (domain_ != policy_domain) {
- LOG(ERROR) << "Invalid user name " << policy_data_->username();
- return VALIDATION_BAD_USERNAME;
- }
-
- return VALIDATION_OK;
-}
-
-CloudPolicyValidatorBase::Status CloudPolicyValidatorBase::CheckPayload() {
- if (!policy_data_->has_policy_value() ||
- !payload_->ParseFromString(policy_data_->policy_value()) ||
- !payload_->IsInitialized()) {
- LOG(ERROR) << "Failed to decode policy payload protobuf";
- return VALIDATION_POLICY_PARSE_ERROR;
- }
-
- return VALIDATION_OK;
-}
-
-// static
-bool CloudPolicyValidatorBase::VerifySignature(const std::string& data,
- const std::string& key,
- const std::string& signature) {
- crypto::SignatureVerifier verifier;
-
- if (!verifier.VerifyInit(kSignatureAlgorithm, sizeof(kSignatureAlgorithm),
- reinterpret_cast<const uint8*>(signature.c_str()),
- signature.size(),
- reinterpret_cast<const uint8*>(key.c_str()),
- key.size())) {
- return false;
- }
- verifier.VerifyUpdate(reinterpret_cast<const uint8*>(data.c_str()),
- data.size());
- return verifier.VerifyFinal();
-}
-
-template class CloudPolicyValidator<em::CloudPolicySettings>;
-template class CloudPolicyValidator<em::ExternalPolicyData>;
-
-} // namespace policy
« no previous file with comments | « chrome/browser/policy/cloud/cloud_policy_validator.h ('k') | chrome/browser/policy/cloud/cloud_policy_validator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698