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

#include "ndn-cxx/security/validation-policy-config.hpp"

#include "ndn-cxx/security/transform/base64-encode.hpp"
#include "ndn-cxx/security/transform/buffer-source.hpp"
#include "ndn-cxx/security/transform/stream-sink.hpp"
#include "ndn-cxx/util/io.hpp"

#include "tests/boost-test.hpp"
#include "tests/unit/security/validator-config/common.hpp"
#include "tests/unit/security/validator-fixture.hpp"

namespace ndn {
namespace security {
inline namespace v2 {
namespace validator_config {
namespace tests {

using namespace ndn::tests;
using namespace ndn::security::tests;

BOOST_AUTO_TEST_SUITE(Security)
BOOST_AUTO_TEST_SUITE(TestValidationPolicyConfig)

BOOST_FIXTURE_TEST_CASE(EmptyConfig, HierarchicalValidatorFixture<ValidationPolicyConfig>)
{
  this->policy.load(ConfigSection{}, "<empty>");

  BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
  BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
  BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 0);
  BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 0);

  Data d("/Security/ValidationPolicyConfig/D");
  this->m_keyChain.sign(d, signingByIdentity(this->identity));
  VALIDATE_FAILURE(d, "Empty policy should reject everything");

  Interest i("/Security/ValidationPolicyConfig/I");
  i.setCanBePrefix(false);
  this->m_keyChain.sign(i, signingByIdentity(this->identity));
  VALIDATE_FAILURE(i, "Empty policy should reject everything");
}

template<typename Packet>
class PacketName;

template<>
class PacketName<Interest>
{
public:
  static std::string
  getName()
  {
    return "interest";
  }
};

template<>
class PacketName<Data>
{
public:
  static std::string
  getName()
  {
    return "data";
  }
};

template<typename PacketType>
class ValidationPolicyConfigFixture : public HierarchicalValidatorFixture<ValidationPolicyConfig>
{
public:
  ValidationPolicyConfigFixture()
    : path(boost::filesystem::path(UNIT_TESTS_TMPDIR) / "security" / "validation-policy-config")
  {
    boost::filesystem::create_directories(path);
    baseConfig = R"CONF(
        rule
        {
          id test-rule-id
          for )CONF" + PacketName<Packet>::getName() + R"CONF(
          filter
          {
            type name
            name )CONF" + identity.getName().toUri() + R"CONF(
            relation is-prefix-of
          }
          checker
          {
            type hierarchical
            sig-type ecdsa-sha256
          }
        }
      )CONF";
  }

  ~ValidationPolicyConfigFixture()
  {
    boost::filesystem::remove_all(path);
  }

protected:
  using Packet = PacketType;

  const boost::filesystem::path path;
  std::string baseConfig;
};

template<typename PacketType>
class LoadStringWithFileAnchor : public ValidationPolicyConfigFixture<PacketType>
{
public:
  LoadStringWithFileAnchor()
  {
    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);

    this->saveIdentityCert(this->identity, (this->path / "identity.ndncert").string());
    this->policy.load(this->baseConfig + R"CONF(
        trust-anchor
        {
          type file
          file-name "trust-anchor.ndncert"
        }
      )CONF", (this->path / "test-config").string());

    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
    BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
  }
};

template<typename PacketType>
class LoadFileWithFileAnchor : public ValidationPolicyConfigFixture<PacketType>
{
public:
  LoadFileWithFileAnchor()
  {
    std::string configFile = (this->path / "config.conf").string();
    {
      std::ofstream config(configFile);
      config << this->baseConfig << R"CONF(
          trust-anchor
          {
            type file
            file-name "trust-anchor.ndncert"
          }
        )CONF";
    }

    this->saveIdentityCert(this->identity, (this->path / "identity.ndncert").string());

    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);

    this->policy.load(configFile);

    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
    BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
  }
};

template<typename PacketType>
class LoadFileWithMultipleFileAnchors : public ValidationPolicyConfigFixture<PacketType>
{
public:
  LoadFileWithMultipleFileAnchors()
  {
    std::string configFile = (this->path / "config.conf").string();
    {
      std::ofstream config(configFile);
      config << this->baseConfig << R"CONF(
          trust-anchor
          {
            type file
            file-name "identity.ndncert"
          }
          trust-anchor
          {
            type file
            file-name "trust-anchor.ndncert"
          }
        )CONF";
    }

    this->saveIdentityCert(this->identity, (this->path / "identity.ndncert").string());

    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);

    this->policy.load(configFile);

    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
    BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
  }
};

template<typename PacketType>
class LoadSectionWithFileAnchor : public ValidationPolicyConfigFixture<PacketType>
{
public:
  LoadSectionWithFileAnchor()
  {
    auto section = makeSection(this->baseConfig + R"CONF(
        trust-anchor
        {
          type file
          file-name "trust-anchor.ndncert"
        }
      )CONF");

    this->saveIdentityCert(this->identity, (this->path / "identity.ndncert").string());

    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);

    this->policy.load(section, (this->path / "test-config").string());

    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
    BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
  }
};

template<typename PacketType>
class LoadStringWithBase64Anchor : public ValidationPolicyConfigFixture<PacketType>
{
public:
  LoadStringWithBase64Anchor()
  {
    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);

    std::ostringstream os;
    {
      using namespace ndn::security::transform;
      const auto& cert = this->identity.getDefaultKey().getDefaultCertificate().wireEncode();
      bufferSource(make_span(cert.wire(), cert.size())) >> base64Encode(false) >> streamSink(os);
    }

    this->policy.load(this->baseConfig + R"CONF(
        trust-anchor
        {
          type base64
          base64-string ")CONF" + os.str() + R"CONF("
        }
      )CONF", (this->path / "test-config").string());

    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
    BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
  }
};

class NoRefresh
{
public:
  static std::string
  getRefreshString()
  {
    return "";
  }
};

class Refresh1h
{
public:
  static std::string
  getRefreshString()
  {
    return "refresh 1h";
  }

  static time::milliseconds
  getRefreshTime()
  {
    return 1_h;
  }
};

class Refresh1m
{
public:
  static std::string
  getRefreshString()
  {
    return "refresh 1m";
  }

  static time::milliseconds
  getRefreshTime()
  {
    return 1_min;
  }
};

class Refresh1s
{
public:
  static std::string
  getRefreshString()
  {
    return "refresh 1s";
  }

  static time::milliseconds
  getRefreshTime()
  {
    return 1_s;
  }
};

template<typename PacketType, typename Refresh = NoRefresh>
class LoadStringWithDirAnchor : public ValidationPolicyConfigFixture<PacketType>
{
public:
  LoadStringWithDirAnchor()
  {
    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);

    boost::filesystem::create_directories(this->path / "keys");
    this->saveIdentityCert(this->identity, (this->path / "keys" / "identity.ndncert").string());

    this->policy.load(this->baseConfig + R"CONF(
        trust-anchor
        {
          type dir
          dir keys
          )CONF" + Refresh::getRefreshString() + R"CONF(
        }
      )CONF", (this->path / "test-config").string());

    BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
    BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
  }
};

using DataPolicies = boost::mpl::vector<LoadStringWithFileAnchor<Data>,
                                        LoadFileWithFileAnchor<Data>,
                                        LoadFileWithMultipleFileAnchors<Data>,
                                        LoadSectionWithFileAnchor<Data>,
                                        LoadStringWithBase64Anchor<Data>,
                                        LoadStringWithDirAnchor<Data>,
                                        LoadStringWithDirAnchor<Data, Refresh1h>,
                                        LoadStringWithDirAnchor<Data, Refresh1m>,
                                        LoadStringWithDirAnchor<Data, Refresh1s>
                                        >;

using InterestPolicies = boost::mpl::vector<LoadStringWithFileAnchor<Interest>,
                                            LoadFileWithFileAnchor<Interest>,
                                            LoadFileWithMultipleFileAnchors<Interest>,
                                            LoadSectionWithFileAnchor<Interest>,
                                            LoadStringWithBase64Anchor<Interest>,
                                            LoadStringWithDirAnchor<Interest>,
                                            LoadStringWithDirAnchor<Interest, Refresh1h>,
                                            LoadStringWithDirAnchor<Interest, Refresh1m>,
                                            LoadStringWithDirAnchor<Interest, Refresh1s>
                                            >;

BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateData, Policy, DataPolicies, Policy)
{
  BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 1);
  BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 0);

  using Packet = typename Policy::Packet;
  Packet unsignedPacket("/Security/ValidatorFixture/Sub1/Sub2/Packet");

  Packet packet = unsignedPacket;
  VALIDATE_FAILURE(packet, "Unsigned");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingWithSha256());
  VALIDATE_FAILURE(packet, "Should not be accepted, doesn't pass checker /localhost/identity/digest-sha256");

  packet = Packet("/localhost/identity/digest-sha256/foobar");
  this->m_keyChain.sign(packet, signingWithSha256());
  VALIDATE_FAILURE(packet, "Should not be accepted, no rule for the name /localhost/identity/digest-sha256");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->identity));
  VALIDATE_SUCCESS(packet, "Should get accepted, as signed by the anchor");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
  VALIDATE_SUCCESS(packet, "Should get accepted, as signed by the policy-compliant cert");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->otherIdentity));
  VALIDATE_FAILURE(packet, "Should fail, as signed by the policy-violating cert");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->subSelfSignedIdentity));
  VALIDATE_FAILURE(packet, "Should fail, because subSelfSignedIdentity is not a trust anchor");
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateInterest, Policy, InterestPolicies, Policy)
{
  BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 0);
  BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 1);

  using Packet = typename Policy::Packet;
  Packet unsignedPacket("/Security/ValidatorFixture/Sub1/Sub2/Packet");
  // All of the packet types inputed to this test case template are Interests, so we can call
  // setCanBePrefix
  unsignedPacket.setCanBePrefix(false);

  Packet packet = unsignedPacket;
  VALIDATE_FAILURE(packet, "Unsigned");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingWithSha256());
  VALIDATE_FAILURE(packet, "Should not be accepted, doesn't pass checker /localhost/identity/digest-sha256");

  packet = Packet("/localhost/identity/digest-sha256/foobar");
  this->m_keyChain.sign(packet, signingWithSha256());
  VALIDATE_FAILURE(packet, "Should not be accepted, no rule for the name /localhost/identity/digest-sha256");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->identity));
  VALIDATE_SUCCESS(packet, "Should get accepted, as signed by the anchor");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
  VALIDATE_FAILURE(packet, "Should fail, as there is no matching rule for data");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->otherIdentity));
  VALIDATE_FAILURE(packet, "Should fail, as signed by the policy-violating cert");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->subSelfSignedIdentity));
  VALIDATE_FAILURE(packet, "Should fail, because subSelfSignedIdentity is not a trust anchor");
}

BOOST_FIXTURE_TEST_CASE(DigestSha256, HierarchicalValidatorFixture<ValidationPolicyConfig>)
{
  BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
  this->policy.load(R"CONF(
      rule
      {
        id test-rule-data-id
        for data
        filter
        {
          type name
          name /Security/ValidatorFixture
          relation is-prefix-of
        }
        checker
        {
          type customized
          sig-type sha256
        }
      }
      rule
      {
        id test-rule-interest-id
        for interest
        filter
        {
          type name
          name /Security/ValidatorFixture
          relation is-prefix-of
        }
        checker
        {
          type customized
          sig-type sha256
        }
      }
    )CONF", "test-config");


  Interest interest("/Security/ValidatorFixture/Sub1/Sub2/Packet");
  interest.setCanBePrefix(false);
  this->m_keyChain.sign(interest, signingWithSha256());
  VALIDATE_SUCCESS(interest, "Should be accepted");

  Data data("/Security/ValidatorFixture/Sub1/Sub2/Packet");
  this->m_keyChain.sign(data, signingWithSha256());
  VALIDATE_SUCCESS(data, "Should be accepted");
}

BOOST_FIXTURE_TEST_CASE(DigestSha256WithKeyLocator, HierarchicalValidatorFixture<ValidationPolicyConfig>)
{
  BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
  this->policy.load(R"CONF(
      rule
      {
        id test-rule-data-id
        for data
        filter
        {
          type name
          name /localhost/identity/digest-sha256
          relation is-prefix-of
        }
        checker
        {
          type customized
          sig-type sha256
          key-locator
          {
            type name
            hyper-relation
            {
              k-regex ^(<>*)$
              k-expand \\1
              h-relation is-prefix-of
              p-regex ^(<>*)$
              p-expand \\1
            }
          }
        }
      }
      rule
      {
        id test-rule-interest-id
        for interest
        filter
        {
          type name
          name /localhost/identity/digest-sha256
          relation is-prefix-of
        }
        checker
        {
          type customized
          sig-type sha256
          key-locator
          {
            type name
            hyper-relation
            {
              k-regex ^(<>*)$
              k-expand \\1
              h-relation is-prefix-of
              p-regex ^(<>*)$
              p-expand \\1
            }
          }
        }
      }
    )CONF", "test-config");


  Interest interest("/localhost/identity/digest-sha256/foobar");
  interest.setCanBePrefix(false);
  this->m_keyChain.sign(interest, signingWithSha256());
  VALIDATE_SUCCESS(interest, "Should be accepted");

  Data data("/localhost/identity/digest-sha256/foobar");
  this->m_keyChain.sign(data, signingWithSha256());
  VALIDATE_SUCCESS(data, "Should be accepted");
}

BOOST_FIXTURE_TEST_CASE(SigTypeCheck, HierarchicalValidatorFixture<ValidationPolicyConfig>)
{
  BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
  this->policy.load(R"CONF(
      rule
      {
        id test-rule-data-id
        for data
        filter
        {
          type name
          name /localhost/identity/digest-sha256
          relation is-prefix-of
        }
        checker
        {
          type customized
          sig-type ecdsa-sha256
          key-locator
          {
            type name
            hyper-relation
            {
              k-regex ^(<>*)$
              k-expand \\1
              h-relation is-prefix-of
              p-regex ^(<>*)$
              p-expand \\1
            }
          }
        }
      }
      rule
      {
        id test-rule-interest-id
        for interest
        filter
        {
          type name
          name /localhost/identity/digest-sha256
          relation is-prefix-of
        }
        checker
        {
          type customized
          sig-type ecdsa-sha256
          key-locator
          {
            type name
            hyper-relation
            {
              k-regex ^(<>*)$
              k-expand \\1
              h-relation is-prefix-of
              p-regex ^(<>*)$
              p-expand \\1
            }
          }
        }
      }
    )CONF", "test-config");


  Interest interest("/localhost/identity/digest-sha256/foobar");
  interest.setCanBePrefix(false);
  this->m_keyChain.sign(interest, signingWithSha256());
  VALIDATE_FAILURE(interest, "Signature type check should fail");

  Data data("/localhost/identity/digest-sha256/foobar");
  this->m_keyChain.sign(data, signingWithSha256());
  VALIDATE_FAILURE(data, "Signature type check should fail");
}

BOOST_FIXTURE_TEST_CASE(Reload, HierarchicalValidatorFixture<ValidationPolicyConfig>)
{
  BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
  this->policy.load(R"CONF(
      rule
      {
        id test-rule-data-id
        for data
        filter
        {
          type name
          name /foo/bar
          relation is-prefix-of
        }
        checker
        {
          type hierarchical
          sig-type ecdsa-sha256
        }
      }
      rule
      {
        id test-rule-interest-id
        for interest
        filter
        {
          type name
          name /foo/bar
          relation is-prefix-of
        }
        checker
        {
          type hierarchical
          sig-type ecdsa-sha256
        }
      }
      trust-anchor
      {
        type dir
        dir keys
        refresh 1h
      }
    )CONF", "test-config");
  BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
  BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
  BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 1);
  BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 1);

  this->policy.load(R"CONF(
      trust-anchor
      {
        type any
      }
    )CONF", "test-config");
  BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
  BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, true);
  BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 0);
  BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 0);
}

using Packets = boost::mpl::vector<Interest, Data>;

BOOST_FIXTURE_TEST_CASE_TEMPLATE(TrustAnchorWildcard, Packet, Packets, ValidationPolicyConfigFixture<Packet>)
{
  this->policy.load(R"CONF(
      trust-anchor
      {
        type any
      }
    )CONF", "test-config");

  BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
  BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, true);
  BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 0);
  BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 0);

  Packet unsignedPacket("/Security/ValidatorFixture/Sub1/Sub2/Packet");

  Packet packet = unsignedPacket;
  VALIDATE_SUCCESS(packet, "Policy should accept everything");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingWithSha256());
  VALIDATE_SUCCESS(packet, "Policy should accept everything");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->identity));
  VALIDATE_SUCCESS(packet, "Policy should accept everything");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
  VALIDATE_SUCCESS(packet, "Policy should accept everything");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->otherIdentity));
  VALIDATE_SUCCESS(packet, "Policy should accept everything");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->subSelfSignedIdentity));
  VALIDATE_SUCCESS(packet, "Policy should accept everything");
}

using RefreshPolicies = boost::mpl::vector<Refresh1h, Refresh1m, Refresh1s>;

template<typename RefreshPolicy>
class RefreshPolicyFixture : public LoadStringWithDirAnchor<Data, RefreshPolicy>
{
};

BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateRefresh, Refresh, RefreshPolicies, RefreshPolicyFixture<Refresh>)
{
  using Packet = Data;
  Packet unsignedPacket("/Security/ValidatorFixture/Sub1/Sub2/Packet");

  boost::filesystem::remove(this->path / "keys" / "identity.ndncert");
  this->advanceClocks(Refresh::getRefreshTime(), 3);

  Packet packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->identity));
  VALIDATE_FAILURE(packet, "Should fail, as the trust anchor should no longer exist");

  packet = unsignedPacket;
  this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
  VALIDATE_FAILURE(packet, "Should fail, as the trust anchor should no longer exist");
}

BOOST_FIXTURE_TEST_CASE(OrphanedPolicyLoad, HierarchicalValidatorFixture<ValidationPolicyConfig>) // Bug #4758
{
  ValidationPolicyConfig policy1;
  BOOST_CHECK_THROW(policy1.load("trust-anchor { type any }", "test-config"), Error);

  // Reloading would have triggered a segfault
  BOOST_CHECK_THROW(policy1.load("trust-anchor { type any }", "test-config"), Error);

  ValidationPolicyConfig policy2;

  std::string config = R"CONF(
      trust-anchor
      {
        type dir
        dir keys
        refresh 1h
      }
    )CONF";

  // Inserting trust anchor would have triggered a segfault
  BOOST_CHECK_THROW(policy2.load(config, "test-config"), Error);
}

BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicyConfig
BOOST_AUTO_TEST_SUITE_END() // Security

} // namespace tests
} // namespace validator_config
} // inline namespace v2
} // namespace security
} // namespace ndn
