/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2016 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 *
 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
 * @author Zhiyi Zhang <zhangzhiyi1919@gmail.com>
 */

#include "validator-config.hpp"
#include "certificate-cache-ttl.hpp"
#include "../util/io.hpp"

#include <boost/filesystem.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/algorithm/string.hpp>

namespace ndn {
namespace security {

const shared_ptr<CertificateCache> ValidatorConfig::DEFAULT_CERTIFICATE_CACHE;
const time::milliseconds ValidatorConfig::DEFAULT_GRACE_INTERVAL(3000);
const time::system_clock::Duration ValidatorConfig::DEFAULT_KEY_TIMESTAMP_TTL = time::hours(1);

ValidatorConfig::ValidatorConfig(Face* face,
                                 const shared_ptr<CertificateCache>& certificateCache,
                                 const time::milliseconds& graceInterval,
                                 const size_t stepLimit,
                                 const size_t maxTrackedKeys,
                                 const time::system_clock::Duration& keyTimestampTtl)
  : Validator(face)
  , m_shouldValidate(true)
  , m_stepLimit(stepLimit)
  , m_certificateCache(certificateCache)
  , m_graceInterval(graceInterval < time::milliseconds::zero() ?
                    DEFAULT_GRACE_INTERVAL : graceInterval)
  , m_maxTrackedKeys(maxTrackedKeys)
  , m_keyTimestampTtl(keyTimestampTtl)
{
  if (m_certificateCache == nullptr && face != nullptr)
    m_certificateCache = make_shared<CertificateCacheTtl>(ref(face->getIoService()));
}

ValidatorConfig::ValidatorConfig(Face& face,
                                 const shared_ptr<CertificateCache>& certificateCache,
                                 const time::milliseconds& graceInterval,
                                 const size_t stepLimit,
                                 const size_t maxTrackedKeys,
                                 const time::system_clock::Duration& keyTimestampTtl)
  : Validator(face)
  , m_shouldValidate(true)
  , m_stepLimit(stepLimit)
  , m_certificateCache(certificateCache)
  , m_graceInterval(graceInterval < time::milliseconds::zero() ?
                    DEFAULT_GRACE_INTERVAL : graceInterval)
  , m_maxTrackedKeys(maxTrackedKeys)
  , m_keyTimestampTtl(keyTimestampTtl)
{
  if (m_certificateCache == nullptr)
    m_certificateCache = make_shared<CertificateCacheTtl>(ref(face.getIoService()));
}

void
ValidatorConfig::load(const std::string& filename)
{
  std::ifstream inputFile;
  inputFile.open(filename.c_str());
  if (!inputFile.good() || !inputFile.is_open()) {
    std::string msg = "Failed to read configuration file: ";
    msg += filename;
    BOOST_THROW_EXCEPTION(security::conf::Error(msg));
  }
  load(inputFile, filename);
  inputFile.close();
}

void
ValidatorConfig::load(const std::string& input, const std::string& filename)
{
  std::istringstream inputStream(input);
  load(inputStream, filename);
}


void
ValidatorConfig::load(std::istream& input, const std::string& filename)
{
  security::conf::ConfigSection tree;
  try {
    boost::property_tree::read_info(input, tree);
  }
  catch (const boost::property_tree::info_parser_error& error) {
    std::stringstream msg;
    msg << "Failed to parse configuration file";
    msg << " " << filename;
    msg << " " << error.message() << " line " << error.line();
    BOOST_THROW_EXCEPTION(security::conf::Error(msg.str()));
  }

  load(tree, filename);
}

void
ValidatorConfig::load(const security::conf::ConfigSection& configSection,
                      const std::string& filename)
{
  BOOST_ASSERT(!filename.empty());

  reset();

  if (configSection.begin() == configSection.end()) {
    std::string msg = "Error processing configuration file";
    msg += ": ";
    msg += filename;
    msg += " no data";
    BOOST_THROW_EXCEPTION(security::conf::Error(msg));
  }

  for (security::conf::ConfigSection::const_iterator i = configSection.begin();
       i != configSection.end(); ++i) {
    const std::string& sectionName = i->first;
    const security::conf::ConfigSection& section = i->second;

    if (boost::iequals(sectionName, "rule")) {
      onConfigRule(section, filename);
    }
    else if (boost::iequals(sectionName, "trust-anchor")) {
      onConfigTrustAnchor(section, filename);
    }
    else {
      std::string msg = "Error processing configuration file";
      msg += " ";
      msg += filename;
      msg += " unrecognized section: " + sectionName;
      BOOST_THROW_EXCEPTION(security::conf::Error(msg));
    }
  }
}

void
ValidatorConfig::onConfigRule(const security::conf::ConfigSection& configSection,
                              const std::string& filename)
{
  using namespace ndn::security::conf;

  ConfigSection::const_iterator propertyIt = configSection.begin();

  // Get rule.id
  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "id"))
    BOOST_THROW_EXCEPTION(Error("Expect <rule.id>!"));

  std::string ruleId = propertyIt->second.data();
  propertyIt++;

  // Get rule.for
  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first,"for"))
    BOOST_THROW_EXCEPTION(Error("Expect <rule.for> in rule: " + ruleId + "!"));

  std::string usage = propertyIt->second.data();
  propertyIt++;

  bool isForData = false;
  if (boost::iequals(usage, "data"))
    isForData = true;
  else if (boost::iequals(usage, "interest"))
    isForData = false;
  else
    BOOST_THROW_EXCEPTION(Error("Unrecognized <rule.for>: " + usage
                                + " in rule: " + ruleId));

  // Get rule.filter(s)
  std::vector<shared_ptr<Filter>> filters;
  for (; propertyIt != configSection.end(); propertyIt++) {
    if (!boost::iequals(propertyIt->first, "filter")) {
      if (boost::iequals(propertyIt->first, "checker"))
        break;
      BOOST_THROW_EXCEPTION(Error("Expect <rule.filter> in rule: " + ruleId));
    }

    filters.push_back(FilterFactory::create(propertyIt->second));
    continue;
  }

  // Get rule.checker(s)
  std::vector<shared_ptr<Checker>> checkers;
  for (; propertyIt != configSection.end(); propertyIt++) {
    if (!boost::iequals(propertyIt->first, "checker"))
      BOOST_THROW_EXCEPTION(Error("Expect <rule.checker> in rule: " + ruleId));

    checkers.push_back(CheckerFactory::create(propertyIt->second, filename));
    continue;
  }

  // Check other stuff
  if (propertyIt != configSection.end())
    BOOST_THROW_EXCEPTION(Error("Expect the end of rule: " + ruleId));

  if (checkers.empty())
    BOOST_THROW_EXCEPTION(Error("No <rule.checker> is specified in rule: " + ruleId));

  if (isForData) {
    shared_ptr<DataRule> rule = make_shared<DataRule>(ruleId);
    for (const auto& filter : filters)
      rule->addFilter(filter);
    for (const auto& checker : checkers)
      rule->addChecker(checker);

    m_dataRules.push_back(rule);
  }
  else {
    shared_ptr<InterestRule> rule = make_shared<InterestRule>(ruleId);;
    for (const auto& filter : filters)
      rule->addFilter(filter);
    for (const auto& checker : checkers)
      rule->addChecker(checker);

    m_interestRules.push_back(rule);
  }
}

void
ValidatorConfig::onConfigTrustAnchor(const security::conf::ConfigSection& configSection,
                                     const std::string& filename)
{
  using namespace ndn::security::conf;
  using namespace boost::filesystem;

  ConfigSection::const_iterator propertyIt = configSection.begin();

  // Get trust-anchor.type
  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
    BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.type>!"));

  std::string type = propertyIt->second.data();
  propertyIt++;

  if (boost::iequals(type, "file")) {
    // Get trust-anchor.file
    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "file-name"))
      BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.file-name>!"));

    std::string file = propertyIt->second.data();
    propertyIt++;

    // Check other stuff
    if (propertyIt != configSection.end())
      BOOST_THROW_EXCEPTION(Error("Expect the end of trust-anchor!"));

    path certfilePath = absolute(file, path(filename).parent_path());
    auto idCert = io::load<v1::IdentityCertificate>(certfilePath.string());

    if (idCert != nullptr) {
      BOOST_ASSERT(idCert->getName().size() >= 1);
      m_staticContainer.add(idCert);
      m_anchors[idCert->getName().getPrefix(-1)] = idCert;
    }
    else
      BOOST_THROW_EXCEPTION(Error("Cannot read certificate from file: " + certfilePath.native()));

    return;
  }
  else if (boost::iequals(type, "base64")) {
    // Get trust-anchor.base64-string
    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "base64-string"))
      BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.base64-string>!"));

    std::stringstream ss(propertyIt->second.data());
    propertyIt++;

    // Check other stuff
    if (propertyIt != configSection.end())
      BOOST_THROW_EXCEPTION(Error("Expect the end of trust-anchor!"));

    auto idCert = io::load<v1::IdentityCertificate>(ss);

    if (idCert != nullptr) {
      BOOST_ASSERT(idCert->getName().size() >= 1);
      m_staticContainer.add(idCert);
      m_anchors[idCert->getName().getPrefix(-1)] = idCert;
    }
    else
      BOOST_THROW_EXCEPTION(Error("Cannot decode certificate from base64-string"));

    return;
  }
  else if (boost::iequals(type, "dir")) {
    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "dir"))
      BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.dir>"));

    std::string dirString(propertyIt->second.data());
    propertyIt++;

    if (propertyIt != configSection.end()) {
      if (boost::iequals(propertyIt->first, "refresh")) {
        using namespace boost::filesystem;

        time::nanoseconds refresh = getRefreshPeriod(propertyIt->second.data());
        propertyIt++;

        if (propertyIt != configSection.end())
          BOOST_THROW_EXCEPTION(Error("Expect the end of trust-anchor"));

        path dirPath = absolute(dirString, path(filename).parent_path());

        m_dynamicContainers.push_back(DynamicTrustAnchorContainer(dirPath, true, refresh));

        m_dynamicContainers.rbegin()->setLastRefresh(time::system_clock::now() - refresh);

        return;
      }
      else
        BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.refresh>!"));
    }
    else {
      using namespace boost::filesystem;

      path dirPath = absolute(dirString, path(filename).parent_path());

      directory_iterator end;

      for (directory_iterator it(dirPath); it != end; it++) {
        auto idCert = io::load<v1::IdentityCertificate>(it->path().string());

        if (idCert != nullptr)
          m_staticContainer.add(idCert);
      }

      return;
    }
  }
  else if (boost::iequals(type, "any")) {
    m_shouldValidate = false;
  }
  else
    BOOST_THROW_EXCEPTION(Error("Unsupported trust-anchor.type: " + type));
}

void
ValidatorConfig::reset()
{
  if (m_certificateCache != nullptr)
    m_certificateCache->reset();
  m_interestRules.clear();
  m_dataRules.clear();

  m_anchors.clear();

  m_staticContainer = TrustAnchorContainer();

  m_dynamicContainers.clear();
}

bool
ValidatorConfig::isEmpty()
{
  return ((m_certificateCache == nullptr || m_certificateCache->isEmpty()) &&
          m_interestRules.empty() && m_dataRules.empty() && m_anchors.empty());
}

time::nanoseconds
ValidatorConfig::getRefreshPeriod(std::string inputString)
{
  char unit = inputString[inputString.size() - 1];
  std::string refreshString = inputString.substr(0, inputString.size() - 1);

  uint32_t refreshPeriod = 0;

  try {
    refreshPeriod = boost::lexical_cast<uint32_t>(refreshString);
  }
  catch (const boost::bad_lexical_cast&) {
    BOOST_THROW_EXCEPTION(Error("Bad number: " + refreshString));
  }

  if (refreshPeriod == 0)
    return getDefaultRefreshPeriod();

  switch (unit) {
  case 'h':
    return time::duration_cast<time::nanoseconds>(time::hours(refreshPeriod));
  case 'm':
    return time::duration_cast<time::nanoseconds>(time::minutes(refreshPeriod));
  case 's':
    return time::duration_cast<time::nanoseconds>(time::seconds(refreshPeriod));
  default:
    BOOST_THROW_EXCEPTION(Error(std::string("Wrong time unit: ") + unit));
  }
}

time::nanoseconds
ValidatorConfig::getDefaultRefreshPeriod()
{
  return time::duration_cast<time::nanoseconds>(time::seconds(3600));
}

void
ValidatorConfig::refreshAnchors()
{
  time::system_clock::TimePoint now = time::system_clock::now();

  bool isRefreshed = false;

  for (auto cIt = m_dynamicContainers.begin();
       cIt != m_dynamicContainers.end() && cIt->getLastRefresh() + cIt->getRefreshPeriod() < now;
       cIt++) {
    isRefreshed = true;
    cIt->refresh();
    cIt->setLastRefresh(now);
  }

  if (isRefreshed) {
    m_anchors.clear();

    for (const auto& cert : m_staticContainer.getAll()) {
      m_anchors[cert->getName().getPrefix(-1)] = cert;
    }

    for (const auto& container : m_dynamicContainers) {
      const CertificateList& certList = container.getAll();

      for (const auto& cert :certList) {
        m_anchors[cert->getName().getPrefix(-1)] = cert;
      }
    }
    m_dynamicContainers.sort(ValidatorConfig::compareDynamicContainer);
  }
}

void
ValidatorConfig::checkPolicy(const Data& data,
                             int nSteps,
                             const OnDataValidated& onValidated,
                             const OnDataValidationFailed& onValidationFailed,
                             std::vector<shared_ptr<ValidationRequest>>& nextSteps)
{
  if (!m_shouldValidate)
    return onValidated(data.shared_from_this());

  bool isMatched = false;
  int8_t checkResult = -1;

  for (const auto& dataRule : m_dataRules) {
    if (dataRule->match(data)) {
      isMatched = true;
      checkResult = dataRule->check(data, onValidated, onValidationFailed);
      break;
    }
  }

  if (!isMatched)
    return onValidationFailed(data.shared_from_this(), "No rule matched!");

  if (checkResult == 0) {
    const Signature& signature = data.getSignature();
    checkSignature(data, signature, nSteps,
                   onValidated, onValidationFailed, nextSteps);
  }
}

void
ValidatorConfig::checkPolicy(const Interest& interest,
                             int nSteps,
                             const OnInterestValidated& onValidated,
                             const OnInterestValidationFailed& onValidationFailed,
                             std::vector<shared_ptr<ValidationRequest>>& nextSteps)
{
  if (!m_shouldValidate)
    return onValidated(interest.shared_from_this());

  // If interestName has less than 4 name components,
  // it is definitely not a signed interest.
  if (interest.getName().size() < signed_interest::MIN_LENGTH)
    return onValidationFailed(interest.shared_from_this(),
                              "Interest is not signed: " + interest.getName().toUri());

  try {
    const Name& interestName = interest.getName();
    Signature signature(interestName[signed_interest::POS_SIG_INFO].blockFromValue(),
                        interestName[signed_interest::POS_SIG_VALUE].blockFromValue());

    if (!signature.hasKeyLocator())
      return onValidationFailed(interest.shared_from_this(), "No valid KeyLocator");

    const KeyLocator& keyLocator = signature.getKeyLocator();

    if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
      return onValidationFailed(interest.shared_from_this(), "Key Locator is not a name");

    Name keyName = v1::IdentityCertificate::certificateNameToPublicKeyName(keyLocator.getName());

    bool isMatched = false;
    int8_t checkResult = -1;

    for (const auto& interestRule : m_interestRules) {
      if (interestRule->match(interest)) {
        isMatched = true;
        checkResult = interestRule->check(interest,
                                          bind(&ValidatorConfig::checkTimestamp, this, _1,
                                               keyName, onValidated, onValidationFailed),
                                          onValidationFailed);
        break;
      }
    }

    if (!isMatched)
      return onValidationFailed(interest.shared_from_this(), "No rule matched!");

    if (checkResult == 0) {
      checkSignature<Interest, OnInterestValidated, OnInterestValidationFailed>
        (interest, signature, nSteps,
         bind(&ValidatorConfig::checkTimestamp, this, _1,
              keyName, onValidated, onValidationFailed),
         onValidationFailed,
         nextSteps);
    }
  }
  catch (const Signature::Error& e) {
    return onValidationFailed(interest.shared_from_this(), "No valid signature");
  }
  catch (const KeyLocator::Error& e){
    return onValidationFailed(interest.shared_from_this(), "No valid KeyLocator");
  }
  catch (const v1::IdentityCertificate::Error& e){
    return onValidationFailed(interest.shared_from_this(), "Cannot determine the signing key");
  }
  catch (const tlv::Error& e){
    return onValidationFailed(interest.shared_from_this(), "Cannot decode signature");
  }
}

void
ValidatorConfig::checkTimestamp(const shared_ptr<const Interest>& interest,
                                const Name& keyName,
                                const OnInterestValidated& onValidated,
                                const OnInterestValidationFailed& onValidationFailed)
{
  const Name& interestName = interest->getName();
  time::system_clock::TimePoint interestTime;

  try {
    interestTime =
      time::fromUnixTimestamp(time::milliseconds(interestName.get(-signed_interest::MIN_LENGTH).toNumber()));
  }
  catch (const tlv::Error& e) {
    return onValidationFailed(interest,
                              "Cannot decode signature related TLVs");
  }

  time::system_clock::TimePoint currentTime = time::system_clock::now();

  LastTimestampMap::iterator timestampIt = m_lastTimestamp.find(keyName);
  if (timestampIt == m_lastTimestamp.end()) {
    if (!(currentTime - m_graceInterval <= interestTime &&
          interestTime <= currentTime + m_graceInterval))
      return onValidationFailed(interest,
                                "The command is not in grace interval: " + interest->getName().toUri());
  }
  else {
    if (interestTime <= timestampIt->second)
      return onValidationFailed(interest,
                                "The command is outdated: " + interest->getName().toUri());
  }

  // Update timestamp
  if (timestampIt == m_lastTimestamp.end()) {
    cleanOldKeys();
    m_lastTimestamp[keyName] = interestTime;
  }
  else {
    timestampIt->second = interestTime;
  }

  return onValidated(interest);
}

void
ValidatorConfig::cleanOldKeys()
{
  if (m_lastTimestamp.size() < m_maxTrackedKeys)
    return;

  LastTimestampMap::iterator timestampIt = m_lastTimestamp.begin();
  LastTimestampMap::iterator end = m_lastTimestamp.end();

  time::system_clock::TimePoint now = time::system_clock::now();
  LastTimestampMap::iterator oldestKeyIt = m_lastTimestamp.begin();
  time::system_clock::TimePoint oldestTimestamp = oldestKeyIt->second;

  while (timestampIt != end) {
    if (now - timestampIt->second > m_keyTimestampTtl) {
      LastTimestampMap::iterator toDelete = timestampIt;
      timestampIt++;
      m_lastTimestamp.erase(toDelete);
      continue;
    }

    if (timestampIt->second < oldestTimestamp) {
      oldestTimestamp = timestampIt->second;
      oldestKeyIt = timestampIt;
    }

    timestampIt++;
  }

  if (m_lastTimestamp.size() >= m_maxTrackedKeys)
    m_lastTimestamp.erase(oldestKeyIt);
}

void
ValidatorConfig::DynamicTrustAnchorContainer::refresh()
{
  using namespace boost::filesystem;

  m_certificates.clear();

  if (m_isDir) {
    directory_iterator end;

    for (directory_iterator it(m_path); it != end; it++) {
      auto idCert = io::load<v1::IdentityCertificate>(it->path().string());

      if (idCert != nullptr)
        m_certificates.push_back(idCert);
    }
  }
  else {
    auto idCert = io::load<v1::IdentityCertificate>(m_path.string());

    if (idCert != nullptr)
      m_certificates.push_back(idCert);
  }
}

template<class Packet, class OnValidated, class OnFailed>
void
ValidatorConfig::checkSignature(const Packet& packet,
                                const Signature& signature,
                                size_t nSteps,
                                const OnValidated& onValidated,
                                const OnFailed& onValidationFailed,
                                std::vector<shared_ptr<ValidationRequest>>& nextSteps)
{
  if (signature.getType() == tlv::DigestSha256) {
    DigestSha256 sigSha256(signature);

    if (verifySignature(packet, sigSha256))
      return onValidated(packet.shared_from_this());
    else
      return onValidationFailed(packet.shared_from_this(), "Sha256 Signature cannot be verified!");
  }

  try {
    switch (signature.getType()) {
      case tlv::SignatureSha256WithRsa:
      case tlv::SignatureSha256WithEcdsa: {
        if (!signature.hasKeyLocator()) {
          return onValidationFailed(packet.shared_from_this(),
                                    "Missing KeyLocator in SignatureInfo");
        }
        break;
      }
      default:
        return onValidationFailed(packet.shared_from_this(), "Unsupported signature type");
    }
  }
  catch (const KeyLocator::Error& e) {
    return onValidationFailed(packet.shared_from_this(),
                              "Cannot decode KeyLocator in public key signature");
  }
  catch (const tlv::Error& e) {
    return onValidationFailed(packet.shared_from_this(), "Cannot decode public key signature");
  }

  if (signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name) {
    return onValidationFailed(packet.shared_from_this(), "Unsupported KeyLocator type");
  }

  const Name& keyLocatorName = signature.getKeyLocator().getName();

  shared_ptr<const v1::Certificate> trustedCert;

  refreshAnchors();

  AnchorList::const_iterator it = m_anchors.find(keyLocatorName);
  if (m_anchors.end() == it && m_certificateCache != nullptr)
    trustedCert = m_certificateCache->getCertificate(keyLocatorName);
  else if (m_anchors.end() != it)
    trustedCert = it->second;

  if (trustedCert != nullptr) {
    if (verifySignature(packet, signature, trustedCert->getPublicKeyInfo()))
      return onValidated(packet.shared_from_this());
    else
      return onValidationFailed(packet.shared_from_this(), "Cannot verify signature");
  }
  else {
    if (m_stepLimit == nSteps)
      return onValidationFailed(packet.shared_from_this(), "Maximum steps of validation reached");

    OnDataValidated onCertValidated =
      bind(&ValidatorConfig::onCertValidated<Packet, OnValidated, OnFailed>,
           this, _1, packet.shared_from_this(), onValidated, onValidationFailed);

    OnDataValidationFailed onCertValidationFailed =
      bind(&ValidatorConfig::onCertFailed<Packet, OnFailed>,
           this, _1, _2, packet.shared_from_this(), onValidationFailed);

    Interest certInterest(keyLocatorName);

    auto nextStep = make_shared<ValidationRequest>(certInterest,
                                                   onCertValidated,
                                                   onCertValidationFailed,
                                                   1, nSteps + 1);

    nextSteps.push_back(nextStep);
    return;
  }
  return onValidationFailed(packet.shared_from_this(), "Unsupported Signature Type");
}

template<class Packet, class OnValidated, class OnFailed>
void
ValidatorConfig::onCertValidated(const shared_ptr<const Data>& signCertificate,
                                 const shared_ptr<const Packet>& packet,
                                 const OnValidated& onValidated,
                                 const OnFailed& onValidationFailed)
{
  if (signCertificate->getContentType() != tlv::ContentType_Key)
    return onValidationFailed(packet,
                              "Cannot retrieve signer's cert: " +
                              signCertificate->getName().toUri());

  shared_ptr<v1::IdentityCertificate> certificate;
  try {
    certificate = make_shared<v1::IdentityCertificate>(*signCertificate);
  }
  catch (const tlv::Error&) {
    return onValidationFailed(packet,
                              "Cannot decode signer's cert: " +
                              signCertificate->getName().toUri());
  }

  if (!certificate->isTooLate() && !certificate->isTooEarly()) {
    if (m_certificateCache != nullptr)
      m_certificateCache->insertCertificate(certificate);

    if (verifySignature(*packet, certificate->getPublicKeyInfo()))
      return onValidated(packet);
    else
      return onValidationFailed(packet,
                                "Cannot verify signature: " + packet->getName().toUri());
  }
  else {
    return onValidationFailed(packet,
                              "Signing certificate " +
                              signCertificate->getName().toUri() + " is no longer valid.");
  }
}

template<class Packet, class OnFailed>
void
ValidatorConfig::onCertFailed(const shared_ptr<const Data>& signCertificate,
                              const std::string& failureInfo,
                              const shared_ptr<const Packet>& packet,
                              const OnFailed& onValidationFailed)
{
  onValidationFailed(packet, failureInfo);
}

} // namespace security
} // namespace ndn
