// 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 "components/policy/core/common/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 "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "crypto/signature_verifier.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "policy/proto/device_management_backend.pb.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>;

#if !defined(OS_ANDROID)
template class CloudPolicyValidator<em::ExternalPolicyData>;
#endif

}  // namespace policy
