/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2017,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NFD 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "command-authenticator.hpp"
#include "core/logger.hpp"

#include <ndn-cxx/security/security-common.hpp>
#include <ndn-cxx/security/verification-helpers.hpp>
#include <ndn-cxx/util/io.hpp>

#include <boost/filesystem.hpp>

namespace nfd {

NFD_LOG_INIT("CommandAuthenticator");
// INFO: configuration change, etc
// DEBUG: per authentication request result

shared_ptr<CommandAuthenticator>
CommandAuthenticator::create()
{
  return shared_ptr<CommandAuthenticator>(new CommandAuthenticator());
}

CommandAuthenticator::CommandAuthenticator()
{
  NFD_LOG_WARN("Command Interest timestamp checking is currently bypassed.");
}

void
CommandAuthenticator::setConfigFile(ConfigFile& configFile)
{
  configFile.addSectionHandler("authorizations",
    bind(&CommandAuthenticator::processConfig, this, _1, _2, _3));
}

void
CommandAuthenticator::processConfig(const ConfigSection& section, bool isDryRun, const std::string& filename)
{
  if (!isDryRun) {
    NFD_LOG_INFO("clear-authorizations");
    for (auto& kv : m_moduleAuth) {
      kv.second.allowAny = false;
      kv.second.certs.clear();
    }
  }

  if (section.empty()) {
    BOOST_THROW_EXCEPTION(ConfigFile::Error("'authorize' is missing under 'authorizations'"));
  }

  int authSectionIndex = 0;
  for (const auto& kv : section) {
    if (kv.first != "authorize") {
      BOOST_THROW_EXCEPTION(ConfigFile::Error(
        "'" + kv.first + "' section is not permitted under 'authorizations'"));
    }
    const ConfigSection& authSection = kv.second;

    std::string certfile;
    try {
      certfile = authSection.get<std::string>("certfile");
    }
    catch (const boost::property_tree::ptree_error&) {
      BOOST_THROW_EXCEPTION(ConfigFile::Error(
        "'certfile' is missing under authorize[" + to_string(authSectionIndex) + "]"));
    }

    bool isAny = false;
    shared_ptr<ndn::security::v2::Certificate> cert;
    if (certfile == "any") {
      isAny = true;
      NFD_LOG_WARN("'certfile any' is intended for demo purposes only and "
                   "SHOULD NOT be used in production environments");
    }
    else {
      using namespace boost::filesystem;
      path certfilePath = absolute(certfile, path(filename).parent_path());
      cert = ndn::io::load<ndn::security::v2::Certificate>(certfilePath.string());
      if (cert == nullptr) {
        BOOST_THROW_EXCEPTION(ConfigFile::Error(
          "cannot load certfile " + certfilePath.string() +
          " for authorize[" + to_string(authSectionIndex) + "]"));
      }
    }

    const ConfigSection* privSection = nullptr;
    try {
      privSection = &authSection.get_child("privileges");
    }
    catch (const boost::property_tree::ptree_error&) {
      BOOST_THROW_EXCEPTION(ConfigFile::Error(
        "'privileges' is missing under authorize[" + to_string(authSectionIndex) + "]"));
    }

    if (privSection->empty()) {
      NFD_LOG_WARN("No privileges granted to certificate " << certfile);
    }
    for (const auto& kv : *privSection) {
      const std::string& module = kv.first;
      auto found = m_moduleAuth.find(module);
      if (found == m_moduleAuth.end()) {
        BOOST_THROW_EXCEPTION(ConfigFile::Error(
          "unknown module '" + module + "' under authorize[" + to_string(authSectionIndex) + "]"));
      }

      if (isDryRun) {
        continue;
      }

      if (isAny) {
        found->second.allowAny = true;
        NFD_LOG_INFO("authorize module=" << module << " signer=any");
      }
      else {
        const Name& keyName = cert->getKeyName();
        found->second.certs.emplace(keyName, *cert);
        NFD_LOG_INFO("authorize module=" << module << " signer=" << keyName <<
                     " certfile=" << certfile);
      }
    }

    ++authSectionIndex;
  }
}

ndn::mgmt::Authorization
CommandAuthenticator::makeAuthorization(const std::string& module, const std::string& verb)
{
  m_moduleAuth[module]; // declares module, so that privilege is recognized

  auto self = this->shared_from_this();
  return [=] (const Name& prefix, const Interest& interest,
              const ndn::mgmt::ControlParameters* params,
              const ndn::mgmt::AcceptContinuation& accept,
              const ndn::mgmt::RejectContinuation& reject) {
    const AuthorizedCerts& authorized = self->m_moduleAuth.at(module);
    if (authorized.allowAny) {
      NFD_LOG_DEBUG("accept " << interest.getName() << " allowAny");
      accept("*");
      return;
    }

    bool isOk = false;
    Name keyName;
    std::tie(isOk, keyName) = CommandAuthenticator::extractKeyName(interest);
    if (!isOk) {
      NFD_LOG_DEBUG("reject " << interest.getName() << " bad-KeyLocator");
      reject(ndn::mgmt::RejectReply::SILENT);
      return;
    }

    auto found = authorized.certs.find(keyName);
    if (found == authorized.certs.end()) {
      NFD_LOG_DEBUG("reject " << interest.getName() << " signer=" << keyName << " not-authorized");
      reject(ndn::mgmt::RejectReply::STATUS403);
      return;
    }

    bool hasGoodSig = ndn::security::verifySignature(interest, found->second);
    if (!hasGoodSig) {
      NFD_LOG_DEBUG("reject " << interest.getName() << " signer=" << keyName << " bad-sig");
      reject(ndn::mgmt::RejectReply::STATUS403);
      return;
    }

    //self->m_validator.validate(interest,
    //  bind([=] {
    //    NFD_LOG_DEBUG("accept " << interest.getName() << " signer=" << keyName);
    //    accept(keyName.toUri());
    //  }),
    //  bind([=] {
    //    NFD_LOG_DEBUG("reject " << interest.getName() << " signer=" << keyName << " invalid-timestamp");
    //    reject(ndn::mgmt::RejectReply::STATUS403);
    //  }));

    /// \todo restore timestamp checking
    NFD_LOG_DEBUG("accept " << interest.getName() << " signer=" << keyName);
    accept(keyName.toUri());
  };
}

std::pair<bool, Name>
CommandAuthenticator::extractKeyName(const Interest& interest)
{
  const Name& name = interest.getName();
  if (name.size() < ndn::command_interest::MIN_SIZE) {
    return {false, Name()};
  }

  ndn::SignatureInfo sig;
  try {
    sig.wireDecode(name[ndn::command_interest::POS_SIG_INFO].blockFromValue());
  }
  catch (const tlv::Error&) {
    return {false, Name()};
  }

  if (!sig.hasKeyLocator()) {
    return {false, Name()};
  }

  const ndn::KeyLocator& keyLocator = sig.getKeyLocator();
  if (keyLocator.getType() != ndn::KeyLocator::KeyLocator_Name) {
    return {false, Name()};
  }

  try {
    return {true, keyLocator.getName()};
  }
  catch (const std::invalid_argument&) {
    return {false, Name()};
  }
}

} // namespace nfd
