/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#ifndef NDN_SECURITY_CONF_CHECKER_HPP
#define NDN_SECURITY_CONF_CHECKER_HPP

#include "key-locator-checker.hpp"
#include "../../util/io.hpp"
#include <boost/algorithm/string.hpp>

#include "common.hpp"

namespace ndn {
namespace security {
namespace conf {

class Checker
{
public:
  typedef function<void(const shared_ptr<const Interest>&)> OnInterestChecked;
  typedef function<void(const shared_ptr<const Interest>&, const std::string&)> OnInterestCheckFailed;
  typedef function<void(const shared_ptr<const Data>&)> OnDataChecked;
  typedef function<void(const shared_ptr<const Data>&, const std::string&)> OnDataCheckFailed;


  virtual
  ~Checker()
  {
  }

  /**
   * @brief check if data satisfies condition defined in the specific checker implementation
   *
   * @param data Data packet
   * @param onValidated Callback function which is called when data is immediately valid
   * @param onValidationFailed Call function which is called when data is immediately invalid
   * @return -1 if data is immediately invalid (onValidationFailed has been called)
   *          1 if data is immediately valid (onValidated has been called)
   *          0 if further signature verification is needed.
   */
  virtual int8_t
  check(const Data& data,
        const OnDataChecked& onValidated,
        const OnDataCheckFailed& onValidationFailed) = 0;

  /**
   * @brief check if interest satisfies condition defined in the specific checker implementation
   *
   * @param interest Interest packet
   * @param onValidated Callback function which is called when interest is immediately valid
   * @param onValidationFailed Call function which is called when interest is immediately invalid
   * @return -1 if interest is immediately invalid (onValidationFailed has been called)
   *          1 if interest is immediately valid (onValidated has been called)
   *          0 if further signature verification is needed.
   */
  virtual int8_t
  check(const Interest& interest,
        const OnInterestChecked& onValidated,
        const OnInterestCheckFailed& onValidationFailed) = 0;
};

class CustomizedChecker : public Checker
{
  enum
    {
      INTEREST_SIG_VALUE = -1,
      INTEREST_SIG_INFO = -2
    };

public:
  CustomizedChecker(uint32_t sigType,
                    shared_ptr<KeyLocatorChecker> keyLocatorChecker)
    : m_sigType(sigType)
    , m_keyLocatorChecker(keyLocatorChecker)
  {
    if (m_sigType == Signature::Sha256WithRsa && !static_cast<bool>(m_keyLocatorChecker))
      throw Error("Strong signature requires KeyLocatorChecker");
  }

  virtual int8_t
  check(const Data& data,
        const OnDataChecked& onValidated,
        const OnDataCheckFailed& onValidationFailed)
  {
    return check(data, data.getSignature(), onValidated, onValidationFailed);
  }

  virtual int8_t
  check(const Interest& interest,
        const OnInterestChecked& onValidated,
        const OnInterestCheckFailed& onValidationFailed)
  {
    const Name& interestName = interest.getName();
    Signature signature(interestName[INTEREST_SIG_INFO].blockFromValue(),
                        interestName[INTEREST_SIG_VALUE].blockFromValue());
    return check(interest, signature, onValidated, onValidationFailed);
  }

private:
  template<class Packet, class OnValidated, class OnFailed>
  int8_t
  check(const Packet& packet, const Signature& signature,
        const OnValidated& onValidated,
        const OnFailed& onValidationFailed)
  {
    if (m_sigType != signature.getType())
      {
        onValidationFailed(packet.shared_from_this(),
                           "Signature type does not match: " +
                           boost::lexical_cast<std::string>(m_sigType) +
                           "!=" +
                           boost::lexical_cast<std::string>(signature.getType()));
        return -1;
      }

    switch (signature.getType())
      {
      case Signature::Sha256WithRsa:
        {
          try
            {
              SignatureSha256WithRsa sig(signature);

              std::string failInfo;
              if (m_keyLocatorChecker->check(packet, sig.getKeyLocator(), failInfo))
                return 0;
              else
                {
                  onValidationFailed(packet.shared_from_this(), failInfo);
                  return -1;
                }
            }
          catch (const SignatureSha256WithRsa::Error& e)
            {
              onValidationFailed(packet.shared_from_this(),
                                 "Cannot decode Sha256WithRsa signature!");
              return -1;
            }
        }
      case Signature::Sha256:
        return 0;
      default:
        {
          onValidationFailed(packet.shared_from_this(),
                             "Unsupported signature type: " +
                             boost::lexical_cast<std::string>(signature.getType()));
          return -1;
        }
      }
  }

private:
  uint32_t m_sigType;
  shared_ptr<KeyLocatorChecker> m_keyLocatorChecker;
};

class HierarchicalChecker : public CustomizedChecker
{
public:
  HierarchicalChecker(uint32_t sigType)
    : CustomizedChecker(sigType,
        make_shared<HyperKeyLocatorNameChecker>("^(<>*)$", "\\1",
                                                "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
                                                "\\1\\2",
                                                KeyLocatorChecker::RELATION_IS_PREFIX_OF))
  {
  }
};

class FixedSignerChecker : public Checker
{
  enum
    {
      INTEREST_SIG_VALUE = -1,
      INTEREST_SIG_INFO = -2
    };
public:
  FixedSignerChecker(uint32_t sigType,
                     const std::vector<shared_ptr<IdentityCertificate> >& signers)
    : m_sigType(sigType)
  {
    for (std::vector<shared_ptr<IdentityCertificate> >::const_iterator it = signers.begin();
         it != signers.end(); it++)
      m_signers[(*it)->getName().getPrefix(-1)] = (*it);
  }

  virtual int8_t
  check(const Data& data,
        const OnDataChecked& onValidated,
        const OnDataCheckFailed& onValidationFailed)
  {
    return check(data, data.getSignature(), onValidated, onValidationFailed);
  }

  virtual int8_t
  check(const Interest& interest,
        const OnInterestChecked& onValidated,
        const OnInterestCheckFailed& onValidationFailed)
  {
    const Name& interestName = interest.getName();
    Signature signature(interestName[INTEREST_SIG_INFO].blockFromValue(),
                        interestName[INTEREST_SIG_VALUE].blockFromValue());
    return check(interest, signature, onValidated, onValidationFailed);
  }

private:
  template<class Packet, class OnValidated, class OnFailed>
  int8_t
  check(const Packet& packet, const Signature& signature,
        const OnValidated& onValidated,
        const OnFailed& onValidationFailed)
  {
    if (m_sigType != signature.getType())
      {
        onValidationFailed(packet.shared_from_this(),
                           "Signature type does not match: "
                           + boost::lexical_cast<std::string>(m_sigType)
                           + "!="
                           + boost::lexical_cast<std::string>(signature.getType()));
        return -1;
      }

    switch (signature.getType())
      {
      case Signature::Sha256WithRsa:
        {
          try
            {
              SignatureSha256WithRsa sig(signature);

              const Name& keyLocatorName = sig.getKeyLocator().getName();
              if (m_signers.find(keyLocatorName) == m_signers.end())
                {
                  onValidationFailed(packet.shared_from_this(),
                                     "Signer is not in the fixed signer list: "
                                     + keyLocatorName.toUri());
                  return -1;
                }

              if (Validator::verifySignature(packet, sig,
                                             m_signers[keyLocatorName]->getPublicKeyInfo()))
                {
                  onValidated(packet.shared_from_this());
                  return 1;
                }
              else
                {
                  onValidationFailed(packet.shared_from_this(),
                                     "Signature cannot be validated!");
                  return -1;
                }
            }
          catch (const KeyLocator::Error& e)
            {
              onValidationFailed(packet.shared_from_this(),
                                 "KeyLocator does not have name!");
              return -1;
            }
          catch (const SignatureSha256WithRsa::Error& e)
            {
              onValidationFailed(packet.shared_from_this(),
                                 "Cannot decode signature!");
              return -1;
            }
        }
      case Signature::Sha256:
        {
          onValidationFailed(packet.shared_from_this(),
                             "FixedSigner does not allow Sha256 signature type!");
          return -1;
        }
      default:
        {
          onValidationFailed(packet.shared_from_this(),
                             "Unsupported signature type: "
                             + boost::lexical_cast<std::string>(signature.getType()));
          return -1;
        }
      }
  }

private:
  typedef std::map<Name, shared_ptr<IdentityCertificate> > SignerList;

  uint32_t m_sigType;
  SignerList m_signers;
};

class CheckerFactory
{
public:
  /**
   * @brief create a checker from configuration file.
   *
   * @param configSection The section containing the definition of checker.
   * @param configFilename The configuration file name.
   * @return a shared pointer to the created checker.
   */
  static shared_ptr<Checker>
  create(const ConfigSection& configSection, const std::string& configFilename)
  {
    ConfigSection::const_iterator propertyIt = configSection.begin();

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

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

    if (boost::iequals(type, "customized"))
      return createCustomizedChecker(configSection, configFilename);
    else if (boost::iequals(type, "hierarchical"))
      return createHierarchicalChecker(configSection, configFilename);
    else if (boost::iequals(type, "fixed-signer"))
      return createFixedSignerChecker(configSection, configFilename);
    else
      throw Error("Unsupported checker type: " + type);
  }

private:
  static shared_ptr<Checker>
  createCustomizedChecker(const ConfigSection& configSection,
                          const std::string& configFilename)
  {
    ConfigSection::const_iterator propertyIt = configSection.begin();
    propertyIt++;

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

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

    // Get checker.key-locator
    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "key-locator"))
      throw Error("Expect <checker.key-locator>!");

    shared_ptr<KeyLocatorChecker> keyLocatorChecker =
      KeyLocatorCheckerFactory::create(propertyIt->second, configFilename);
    propertyIt++;

    if (propertyIt != configSection.end())
      throw Error("Expect the end of checker!");

    return make_shared<CustomizedChecker>(boost::cref(getSigType(sigType)),
                                          boost::cref(keyLocatorChecker));
  }

  static shared_ptr<Checker>
  createHierarchicalChecker(const ConfigSection& configSection,
                            const std::string& configFilename)
  {
    ConfigSection::const_iterator propertyIt = configSection.begin();
    propertyIt++;

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

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

    if (propertyIt != configSection.end())
      throw Error("Expect the end of checker!");

    return make_shared<HierarchicalChecker>(boost::cref(getSigType(sigType)));
  }

  static shared_ptr<Checker>
  createFixedSignerChecker(const ConfigSection& configSection,
                           const std::string& configFilename)
  {
    ConfigSection::const_iterator propertyIt = configSection.begin();
    propertyIt++;

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

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

    std::vector<shared_ptr<IdentityCertificate> > signers;
    for (; propertyIt != configSection.end(); propertyIt++)
      {
        if (!boost::iequals(propertyIt->first, "signer"))
          throw Error("Expect <checker.signer> but get <checker."
                      + propertyIt->first + ">");

        signers.push_back(getSigner(propertyIt->second, configFilename));
      }

    if (propertyIt != configSection.end())
      throw Error("Expect the end of checker!");

    return shared_ptr<FixedSignerChecker>(new FixedSignerChecker(getSigType(sigType),
                                                                 signers));
  }

  static shared_ptr<IdentityCertificate>
  getSigner(const ConfigSection& configSection, const std::string& configFilename)
  {
    using namespace boost::filesystem;

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

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

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

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

        path certfilePath = absolute(propertyIt->second.data(),
                                     path(configFilename).parent_path());
        propertyIt++;

        if (propertyIt != configSection.end())
          throw Error("Expect the end of checker.signer");

        shared_ptr<IdentityCertificate> idCert
          = io::load<IdentityCertificate>(certfilePath.c_str());

        if (static_cast<bool>(idCert))
          return idCert;
        else
          throw Error("Cannot read certificate from file: "
                      + certfilePath.native());
      }
    else if (boost::iequals(type, "base64"))
      {
        // Get checker.signer.base64-string
        if (propertyIt == configSection.end() ||
            !boost::iequals(propertyIt->first, "base64-string"))
          throw Error("Expect <checker.signer.base64-string>!");

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

        if (propertyIt != configSection.end())
          throw Error("Expect the end of checker.signer");

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

        if (static_cast<bool>(idCert))
          return idCert;
        else
          throw Error("Cannot decode certificate from string");
      }
    else
      throw Error("Unsupported checker.signer type: " + type);
  }

  static int32_t
  getSigType(const std::string& sigType)
  {
    if (boost::iequals(sigType, "rsa-sha256"))
      return Signature::Sha256WithRsa;
    else if (boost::iequals(sigType, "sha256"))
      return Signature::Sha256;
    else
      return -1;
  }
};

} // namespace conf
} // namespace security
} // namespace ndn

#endif // NDN_SECURITY_SEC_CONF_RULE_SIGNER_HPP
