/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2014 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/>
 */

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

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 (!static_cast<bool>(m_certificateCache) && 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 (!static_cast<bool>(m_certificateCache))
    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;
      throw 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 (boost::property_tree::info_parser_error& error)
    {
      std::stringstream msg;
      msg << "Failed to parse configuration file";
      msg << " " << filename;
      msg << " " << error.message() << " line " << error.line();
      throw 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";
      throw 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;
          throw 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"))
    throw Error("Expect <rule.id>!");

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

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

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

  bool isForData;
  if (boost::iequals(usage, "data"))
    isForData = true;
  else if (boost::iequals(usage, "interest"))
    isForData = false;
  else
    throw 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;
          throw 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"))
        throw Error("Expect <rule.checker> in rule: " + ruleId);

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

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

  if (checkers.size() == 0)
    throw Error("No <rule.checker> is specified in rule: " + ruleId);

  if (isForData)
    {
      shared_ptr<DataRule> rule(new DataRule(ruleId));
      for (size_t i = 0; i < filters.size(); i++)
        rule->addFilter(filters[i]);
      for (size_t i = 0; i < checkers.size(); i++)
        rule->addChecker(checkers[i]);

      m_dataRules.push_back(rule);
    }
  else
    {
      shared_ptr<InterestRule> rule(new InterestRule(ruleId));
      for (size_t i = 0; i < filters.size(); i++)
        rule->addFilter(filters[i]);
      for (size_t i = 0; i < checkers.size(); i++)
        rule->addChecker(checkers[i]);

      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"))
    throw 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"))
        throw Error("Expect <trust-anchor.file-name>!");

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

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

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

      if (static_cast<bool>(idCert))
        {
          BOOST_ASSERT(idCert->getName().size() >= 1);
          m_staticContainer.add(idCert);
          m_anchors[idCert->getName().getPrefix(-1)] = idCert;
        }
      else
        throw 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"))
        throw Error("Expect <trust-anchor.base64-string>!");

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

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

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

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

      return;
    }
  else if (boost::iequals(type, "dir"))
    {
      if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "dir"))
        throw 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())
                throw 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
            throw 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++)
            {
              shared_ptr<IdentityCertificate> idCert =
                io::load<IdentityCertificate>(it->path().string());

              if (static_cast<bool>(idCert))
                m_staticContainer.add(idCert);
            }

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

void
ValidatorConfig::reset()
{
  if (static_cast<bool>(m_certificateCache))
    m_certificateCache->reset();
  m_interestRules.clear();
  m_dataRules.clear();

  m_anchors.clear();

  m_staticContainer = TrustAnchorContainer();

  m_dynamicContainers.clear();
}

bool
ValidatorConfig::isEmpty()
{
  if ((!static_cast<bool>(m_certificateCache) || m_certificateCache->isEmpty()) &&
      m_interestRules.empty() &&
      m_dataRules.empty() &&
      m_anchors.empty())
    return true;
  return false;
}

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

  uint32_t number;

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

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

  switch (unit)
    {
    case 'h':
      return time::duration_cast<time::nanoseconds>(time::hours(number));
    case 'm':
      return time::duration_cast<time::nanoseconds>(time::minutes(number));
    case 's':
      return time::duration_cast<time::nanoseconds>(time::seconds(number));
    default:
      throw 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 (DynamicContainers::iterator cIt = m_dynamicContainers.begin();
       cIt != m_dynamicContainers.end(); cIt++)
    {
      if (cIt->getLastRefresh() + cIt->getRefreshPeriod() < now)
        {
          isRefreshed = true;
          cIt->refresh();
          cIt->setLastRefresh(now);
        }
      else
        break;
    }

  if (isRefreshed)
    {
      m_anchors.clear();

      for (CertificateList::const_iterator it = m_staticContainer.getAll().begin();
           it != m_staticContainer.getAll().end(); it++)
        {
          m_anchors[(*it)->getName().getPrefix(-1)] = (*it);
        }

      for (DynamicContainers::iterator cIt = m_dynamicContainers.begin();
           cIt != m_dynamicContainers.end(); cIt++)
        {
          const CertificateList& certList = cIt->getAll();

          for (CertificateList::const_iterator it = certList.begin();
               it != certList.end(); it++)
            {
              m_anchors[(*it)->getName().getPrefix(-1)] = (*it);
            }
        }
      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 (DataRuleList::iterator it = m_dataRules.begin();
       it != m_dataRules.end(); it++)
    {
      if ((*it)->match(data))
        {
          isMatched = true;
          checkResult = (*it)->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 = IdentityCertificate::certificateNameToPublicKeyName(keyLocator.getName());

      bool isMatched = false;
      int8_t checkResult = -1;

      for (InterestRuleList::iterator it = m_interestRules.begin();
           it != m_interestRules.end(); it++)
        {
          if ((*it)->match(interest))
            {
              isMatched = true;
              checkResult = (*it)->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 (Signature::Error& e)
    {
      return onValidationFailed(interest.shared_from_this(),
                                "No valid signature");
    }
  catch (KeyLocator::Error& e)
    {
      return onValidationFailed(interest.shared_from_this(),
                                "No valid KeyLocator");
    }
  catch (tlv::Error& e)
    {
      return onValidationFailed(interest.shared_from_this(),
                                "Cannot decode signature");
    }
  catch (IdentityCertificate::Error& e)
    {
      return onValidationFailed(interest.shared_from_this(),
                                "Cannot determine the signing key");
    }
}

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 (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++)
        {
          shared_ptr<IdentityCertificate> idCert =
            io::load<IdentityCertificate>(it->path().string());

          if (static_cast<bool>(idCert))
            m_certificates.push_back(idCert);
        }
    }
  else
    {
      shared_ptr<IdentityCertificate> idCert =
        io::load<IdentityCertificate>(m_path.string());

      if (static_cast<bool>(idCert))
        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 (KeyLocator::Error& e) {
    return onValidationFailed(packet.shared_from_this(),
                              "Cannot decode KeyLocator in public key signature");
  }
  catch (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 Certificate> trustedCert;

  refreshAnchors();

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

  if (static_cast<bool>(trustedCert))
    {
      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);

      shared_ptr<ValidationRequest> 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)
{
  shared_ptr<IdentityCertificate> certificate =
    make_shared<IdentityCertificate>(*signCertificate);

  if (!certificate->isTooLate() && !certificate->isTooEarly())
    {
      if (static_cast<bool>(m_certificateCache))
        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 ndn
