add policy checker
Change-Id: I90c50d15b1d9d97832c66ce90e39524729f12a0f
diff --git a/core/conf/checker.cpp b/core/conf/checker.cpp
new file mode 100644
index 0000000..8c63458
--- /dev/null
+++ b/core/conf/checker.cpp
@@ -0,0 +1,176 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#include "checker.hpp"
+
+#include <boost/algorithm/string.hpp>
+
+namespace nsl {
+namespace conf {
+
+Checker::~Checker()
+{
+}
+
+CustomizedChecker::CustomizedChecker(uint32_t sigType,
+ shared_ptr<KeyLocatorChecker> keyLocatorChecker)
+ : m_sigType(sigType)
+ , m_keyLocatorChecker(keyLocatorChecker)
+{
+ switch (sigType) {
+ case tlv::SignatureSha256WithRsa:
+ case tlv::SignatureSha256WithEcdsa:
+ {
+ if (!static_cast<bool>(m_keyLocatorChecker))
+ throw Error("Strong signature requires KeyLocatorChecker");
+
+ return;
+ }
+ case tlv::DigestSha256:
+ return;
+ default:
+ throw Error("Unsupported signature type");
+ }
+}
+
+bool
+CustomizedChecker::check(const Data& data)
+{
+ const Signature signature = data.getSignature();
+ if (m_sigType != signature.getType())
+ return false;
+
+ if (signature.getType() == tlv::DigestSha256)
+ return true;
+
+ try {
+ switch (signature.getType()) {
+ case tlv::SignatureSha256WithRsa:
+ case tlv::SignatureSha256WithEcdsa:
+ {
+ if (!signature.hasKeyLocator())
+ return false;
+ break;
+ }
+ default:
+ return false;
+ }
+ }
+ catch (KeyLocator::Error&) {
+ return false;
+ }
+ catch (tlv::Error& e) {
+ return false;
+ }
+
+ std::string failInfo;
+ return m_keyLocatorChecker->check(data, signature.getKeyLocator(), failInfo);
+}
+
+HierarchicalChecker::HierarchicalChecker(uint32_t sigType)
+ : CustomizedChecker(sigType,
+ make_shared<HyperKeyLocatorNameChecker>("^(<>*)$", "\\1",
+ "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
+ "\\1\\2",
+ KeyLocatorChecker::RELATION_IS_PREFIX_OF))
+{
+}
+
+shared_ptr<Checker>
+CheckerFactory::create(const ConfigSection& configSection)
+{
+ 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);
+ else if (boost::iequals(type, "hierarchical"))
+ return createHierarchicalChecker(configSection);
+ else
+ throw Error("Unsupported checker type: " + type);
+}
+
+shared_ptr<Checker>
+CheckerFactory::createCustomizedChecker(const ConfigSection& configSection)
+{
+ 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);
+ propertyIt++;
+
+ if (propertyIt != configSection.end())
+ throw Error("Expect the end of checker");
+
+ return make_shared<CustomizedChecker>(getSigType(sigType), keyLocatorChecker);
+}
+
+shared_ptr<Checker>
+CheckerFactory::createHierarchicalChecker(const ConfigSection& configSection)
+{
+ 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>(getSigType(sigType));
+}
+
+uint32_t
+CheckerFactory::getSigType(const std::string& sigType)
+{
+ if (boost::iequals(sigType, "rsa-sha256"))
+ return tlv::SignatureSha256WithRsa;
+ else if (boost::iequals(sigType, "ecdsa-sha256"))
+ return tlv::SignatureSha256WithEcdsa;
+ else if (boost::iequals(sigType, "sha256"))
+ return tlv::DigestSha256;
+ else
+ throw Error("Unsupported signature type");
+}
+
+} // namespace conf
+} // namespace nsl
diff --git a/core/conf/checker.hpp b/core/conf/checker.hpp
new file mode 100644
index 0000000..bc253f3
--- /dev/null
+++ b/core/conf/checker.hpp
@@ -0,0 +1,98 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#ifndef NSL_CONF_CHECKER_HPP
+#define NSL_CONF_CHECKER_HPP
+
+#include "common.hpp"
+#include "config.hpp"
+#include "key-locator-checker.hpp"
+
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace nsl {
+namespace conf {
+
+class Checker
+{
+public:
+ virtual
+ ~Checker();
+
+ /**
+ * @brief check if data satisfies condition defined in the specific checker implementation
+ *
+ * @param data Data packet
+ * @return false if data cannot pass checking
+ */
+ virtual bool
+ check(const Data& data) = 0;
+};
+
+class CustomizedChecker : public Checker
+{
+public:
+ CustomizedChecker(uint32_t sigType, shared_ptr<KeyLocatorChecker> keyLocatorChecker);
+
+ virtual bool
+ check(const Data& data);
+
+private:
+ uint32_t m_sigType;
+ shared_ptr<KeyLocatorChecker> m_keyLocatorChecker;
+};
+
+class HierarchicalChecker : public CustomizedChecker
+{
+public:
+ explicit
+ HierarchicalChecker(uint32_t sigType);
+};
+
+class CheckerFactory
+{
+public:
+ /**
+ * @brief create a checker from configuration file.
+ *
+ * @param configSection The section containing the definition of checker.
+ * @return a shared pointer to the created checker.
+ */
+ static shared_ptr<Checker>
+ create(const ConfigSection& configSection);
+
+private:
+ static shared_ptr<Checker>
+ createCustomizedChecker(const ConfigSection& configSection);
+
+ static shared_ptr<Checker>
+ createHierarchicalChecker(const ConfigSection& configSection);
+
+ static uint32_t
+ getSigType(const std::string& sigType);
+};
+
+} // namespace conf
+} // namespace nsl
+
+#endif // NSL_CONF_CHECKER_HPP
diff --git a/core/conf/config.hpp b/core/conf/config.hpp
new file mode 100644
index 0000000..ec3d5f5
--- /dev/null
+++ b/core/conf/config.hpp
@@ -0,0 +1,45 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#ifndef NSL_CONF_CONFIG_HPP
+#define NSL_CONF_CONFIG_HPP
+
+#include <boost/property_tree/ptree.hpp>
+
+namespace nsl {
+namespace conf {
+
+typedef boost::property_tree::ptree ConfigSection;
+
+class Error : public std::runtime_error
+{
+public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+};
+
+} // namespace conf
+} // namespace nsl
+
+#endif // NSL_CONF_CONFIG_HPP
diff --git a/core/conf/filter.cpp b/core/conf/filter.cpp
new file mode 100644
index 0000000..6838d92
--- /dev/null
+++ b/core/conf/filter.cpp
@@ -0,0 +1,158 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+
+#include "filter.hpp"
+
+#include <boost/algorithm/string.hpp>
+
+namespace nsl {
+namespace conf {
+
+Filter::~Filter()
+{
+}
+
+bool
+Filter::match(const Data& data)
+{
+ return matchName(data.getName());
+}
+
+RelationNameFilter::RelationNameFilter(const Name& name, Relation relation)
+ : m_name(name)
+ , m_relation(relation)
+{
+}
+
+RelationNameFilter::~RelationNameFilter()
+{
+}
+
+bool
+RelationNameFilter::matchName(const Name& name)
+{
+ switch (m_relation) {
+ case RELATION_EQUAL:
+ return (name == m_name);
+ case RELATION_IS_PREFIX_OF:
+ return m_name.isPrefixOf(name);
+ case RELATION_IS_STRICT_PREFIX_OF:
+ return (m_name.isPrefixOf(name) && m_name.size() < name.size());
+ default:
+ return false;
+ }
+}
+
+RegexNameFilter::RegexNameFilter(const ndn::Regex& regex)
+ : m_regex(regex)
+{
+}
+
+RegexNameFilter::~RegexNameFilter()
+{
+}
+
+bool
+RegexNameFilter::matchName(const Name& name)
+{
+ return m_regex.match(name);
+}
+
+shared_ptr<Filter>
+FilterFactory::create(const ConfigSection& configSection)
+{
+ ConfigSection::const_iterator propertyIt = configSection.begin();
+
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
+ throw Error("Expect <filter.type>!");
+
+ std::string type = propertyIt->second.data();
+
+ if (boost::iequals(type, "name"))
+ return createNameFilter(configSection);
+ else
+ throw Error("Unsupported filter.type: " + type);
+}
+
+shared_ptr<Filter>
+FilterFactory::createNameFilter(const ConfigSection& configSection)
+{
+ ConfigSection::const_iterator propertyIt = configSection.begin();
+ propertyIt++;
+
+ if (propertyIt == configSection.end())
+ throw Error("Expect more properties for filter(name)");
+
+ if (boost::iequals(propertyIt->first, "name")) {
+ // Get filter.name
+ Name name;
+ try {
+ name = Name(propertyIt->second.data());
+ }
+ catch (Name::Error& e) {
+ throw Error("Wrong filter.name: " + propertyIt->second.data());
+ }
+
+ propertyIt++;
+
+ // Get filter.relation
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
+ throw Error("Expect <filter.relation>!");
+
+ std::string relationString = propertyIt->second.data();
+ propertyIt++;
+
+ RelationNameFilter::Relation relation;
+ if (boost::iequals(relationString, "equal"))
+ relation = RelationNameFilter::RELATION_EQUAL;
+ else if (boost::iequals(relationString, "is-prefix-of"))
+ relation = RelationNameFilter::RELATION_IS_PREFIX_OF;
+ else if (boost::iequals(relationString, "is-strict-prefix-of"))
+ relation = RelationNameFilter::RELATION_IS_STRICT_PREFIX_OF;
+ else
+ throw Error("Unsupported relation: " + relationString);
+
+ if (propertyIt != configSection.end())
+ throw Error("Expect the end of filter!");
+
+ return make_shared<RelationNameFilter>(name, relation);
+ }
+ else if (boost::iequals(propertyIt->first, "regex")) {
+ std::string regexString = propertyIt->second.data();
+ propertyIt++;
+
+ if (propertyIt != configSection.end())
+ throw Error("Expect the end of filter!");
+
+ try {
+ return shared_ptr<RegexNameFilter>(new RegexNameFilter(regexString));
+ }
+ catch (ndn::Regex::Error& e) {
+ throw Error("Wrong filter.regex: " + regexString);
+ }
+ }
+ else
+ throw Error("Wrong filter(name) properties");
+}
+
+} // namespace conf
+} // namespace ndn
diff --git a/core/conf/filter.hpp b/core/conf/filter.hpp
new file mode 100644
index 0000000..fe399f5
--- /dev/null
+++ b/core/conf/filter.hpp
@@ -0,0 +1,110 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#ifndef NSL_CONF_FILTER_HPP
+#define NSL_CONF_FILTER_HPP
+
+#include "common.hpp"
+#include "config.hpp"
+#include <ndn-cxx/util/regex.hpp>
+
+namespace nsl {
+namespace conf {
+
+/**
+ * @brief Filter is one of the classes used by ValidatorConfig.
+ *
+ * The ValidatorConfig class consists of a set of rules.
+ * The Filter class is a part of a rule and is used to match packet.
+ * Matched packets will be checked against the checkers defined in the rule.
+ */
+
+class Filter
+{
+public:
+
+ virtual
+ ~Filter();
+
+ bool
+ match(const Data& data);
+
+protected:
+ virtual bool
+ matchName(const Name& name) = 0;
+};
+
+class RelationNameFilter : public Filter
+{
+public:
+ enum Relation
+ {
+ RELATION_EQUAL,
+ RELATION_IS_PREFIX_OF,
+ RELATION_IS_STRICT_PREFIX_OF
+ };
+
+ RelationNameFilter(const Name& name, Relation relation);
+
+ virtual
+ ~RelationNameFilter();
+
+protected:
+ virtual bool
+ matchName(const Name& name);
+
+private:
+ Name m_name;
+ Relation m_relation;
+};
+
+class RegexNameFilter : public Filter
+{
+public:
+ explicit
+ RegexNameFilter(const ndn::Regex& regex);
+
+ virtual
+ ~RegexNameFilter();
+
+protected:
+ virtual bool
+ matchName(const Name& name);
+
+private:
+ ndn::Regex m_regex;
+};
+
+class FilterFactory
+{
+public:
+ static shared_ptr<Filter>
+ create(const ConfigSection& configSection);
+
+private:
+ static shared_ptr<Filter>
+ createNameFilter(const ConfigSection& configSection);
+};
+
+} // namespace conf
+} // namespace ndn
+
+#endif // NSL_CONF_FILTER_HPP
diff --git a/core/conf/key-locator-checker.cpp b/core/conf/key-locator-checker.cpp
new file mode 100644
index 0000000..2fd27bc
--- /dev/null
+++ b/core/conf/key-locator-checker.cpp
@@ -0,0 +1,277 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#include "key-locator-checker.hpp"
+
+#include <boost/algorithm/string.hpp>
+
+namespace nsl {
+namespace conf {
+
+KeyLocatorChecker::~KeyLocatorChecker()
+{
+}
+
+bool
+KeyLocatorChecker::check(const Data& data, const KeyLocator& keyLocator, std::string& failInfo)
+{
+ return check(data.getName(), keyLocator, failInfo);
+}
+
+bool
+KeyLocatorChecker::checkRelation(const Relation& relation, const Name& name1, const Name& name2)
+{
+ switch (relation) {
+ case RELATION_EQUAL:
+ return (name1 == name2);
+ case RELATION_IS_PREFIX_OF:
+ return name1.isPrefixOf(name2);
+ case RELATION_IS_STRICT_PREFIX_OF:
+ return (name1.isPrefixOf(name2) && name1 != name2);
+ default:
+ return false;
+ }
+}
+
+RelationKeyLocatorNameChecker::RelationKeyLocatorNameChecker(const Name& name,
+ const KeyLocatorChecker::Relation& relation)
+ : m_name(name)
+ , m_relation(relation)
+{
+}
+
+bool
+RelationKeyLocatorNameChecker::check(const Name& packetName,
+ const KeyLocator& keyLocator,
+ std::string& failInfo)
+{
+ try {
+ if (checkRelation(m_relation, m_name, keyLocator.getName()))
+ return true;
+
+ failInfo = "KeyLocatorChecker failed";
+ return false;
+ }
+ catch (KeyLocator::Error&) {
+ failInfo = "KeyLocator does not have name";
+ return false;
+ }
+}
+
+RegexKeyLocatorNameChecker::RegexKeyLocatorNameChecker(const ndn::Regex& regex)
+ : m_regex(regex)
+{
+}
+
+bool
+RegexKeyLocatorNameChecker::check(const Name& packetName,
+ const KeyLocator& keyLocator,
+ std::string& failInfo)
+{
+ try {
+ if (m_regex.match(keyLocator.getName()))
+ return true;
+
+ failInfo = "KeyLocatorChecker failed";
+ return false;
+ }
+ catch (KeyLocator::Error&) {
+ failInfo = "KeyLocator does not have name";
+ return false;
+ }
+}
+
+HyperKeyLocatorNameChecker::HyperKeyLocatorNameChecker(const std::string& pExpr,
+ const std::string pExpand,
+ const std::string& kExpr,
+ const std::string kExpand,
+ const Relation& hyperRelation)
+ : m_hyperPRegex(new ndn::Regex(pExpr, pExpand))
+ , m_hyperKRegex(new ndn::Regex(kExpr, kExpand))
+ , m_hyperRelation(hyperRelation)
+{
+}
+
+bool
+HyperKeyLocatorNameChecker::check(const Name& packetName,
+ const KeyLocator& keyLocator,
+ std::string& failInfo)
+{
+ try {
+ if (m_hyperPRegex->match(packetName) &&
+ m_hyperKRegex->match(keyLocator.getName()) &&
+ checkRelation(m_hyperRelation,
+ m_hyperKRegex->expand(),
+ m_hyperPRegex->expand()))
+ return true;
+
+ failInfo = "KeyLocatorChecker failed";
+ return false;
+ }
+ catch (KeyLocator::Error&) {
+ failInfo = "KeyLocator does not have name";
+ return false;
+ }
+}
+
+shared_ptr<KeyLocatorChecker>
+KeyLocatorCheckerFactory::create(const ConfigSection& configSection)
+{
+ ConfigSection::const_iterator propertyIt = configSection.begin();
+
+ // Get checker.key-locator.type
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
+ throw Error("Expect <checker.key-locator.type>");
+
+ std::string type = propertyIt->second.data();
+
+ if (boost::iequals(type, "name"))
+ return createKeyLocatorNameChecker(configSection);
+ else
+ throw Error("Unsupported checker.key-locator.type: " + type);
+}
+
+shared_ptr<KeyLocatorChecker>
+KeyLocatorCheckerFactory::createKeyLocatorNameChecker(const ConfigSection& configSection)
+{
+ ConfigSection::const_iterator propertyIt = configSection.begin();
+ propertyIt++;
+
+ if (propertyIt == configSection.end())
+ throw Error("Expect more checker.key-locator properties");
+
+ if (boost::iequals(propertyIt->first, "name")) {
+ Name name;
+ try {
+ name = Name(propertyIt->second.data());
+ }
+ catch (Name::Error& e) {
+ throw Error("Invalid checker.key-locator.name: " +
+ propertyIt->second.data());
+ }
+ propertyIt++;
+
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
+ throw Error("Expect <checker.key-locator.relation>!");
+
+ std::string relationString = propertyIt->second.data();
+ propertyIt++;
+
+ KeyLocatorChecker::Relation relation;
+ if (boost::iequals(relationString, "equal"))
+ relation = KeyLocatorChecker::RELATION_EQUAL;
+ else if (boost::iequals(relationString, "is-prefix-of"))
+ relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
+ else if (boost::iequals(relationString, "is-strict-prefix-of"))
+ relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
+ else
+ throw Error("Unsupported relation: " + relationString);
+
+ if (propertyIt != configSection.end())
+ throw Error("Expect the end of checker.key-locator!");
+
+ return shared_ptr<RelationKeyLocatorNameChecker>
+ (new RelationKeyLocatorNameChecker(name, relation));
+ }
+ else if (boost::iequals(propertyIt->first, "regex")) {
+ std::string regexString = propertyIt->second.data();
+ propertyIt++;
+
+ if (propertyIt != configSection.end())
+ throw Error("Expect the end of checker.key-locator!");
+
+ try {
+ return shared_ptr<RegexKeyLocatorNameChecker>
+ (new RegexKeyLocatorNameChecker(regexString));
+ }
+ catch (ndn::Regex::Error& e) {
+ throw Error("Invalid checker.key-locator.regex: " + regexString);
+ }
+ }
+ else if (boost::iequals(propertyIt->first, "hyper-relation")) {
+ const ConfigSection& hSection = propertyIt->second;
+
+ ConfigSection::const_iterator hPropertyIt = hSection.begin();
+
+ // Get k-regex
+ if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-regex"))
+ throw Error("Expect <checker.key-locator.hyper-relation.k-regex>!");
+
+ std::string kRegex = hPropertyIt->second.data();
+ hPropertyIt++;
+
+ // Get k-expand
+ if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-expand"))
+ throw Error("Expect <checker.key-locator.hyper-relation.k-expand>!");
+
+ std::string kExpand = hPropertyIt->second.data();
+ hPropertyIt++;
+
+ // Get h-relation
+ if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "h-relation"))
+ throw Error("Expect <checker.key-locator.hyper-relation.h-relation>!");
+
+ std::string hRelation = hPropertyIt->second.data();
+ hPropertyIt++;
+
+ // Get p-regex
+ if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-regex"))
+ throw Error("Expect <checker.key-locator.hyper-relation.p-regex>!");
+
+ std::string pRegex = hPropertyIt->second.data();
+ hPropertyIt++;
+
+ // Get p-expand
+ if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-expand"))
+ throw Error("Expect <checker.key-locator.hyper-relation.p-expand>!");
+
+ std::string pExpand = hPropertyIt->second.data();
+ hPropertyIt++;
+
+ if (hPropertyIt != hSection.end())
+ throw Error("Expect the end of checker.key-locator.hyper-relation!");
+
+ KeyLocatorChecker::Relation relation;
+ if (boost::iequals(hRelation, "equal"))
+ relation = KeyLocatorChecker::RELATION_EQUAL;
+ else if (boost::iequals(hRelation, "is-prefix-of"))
+ relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
+ else if (boost::iequals(hRelation, "is-strict-prefix-of"))
+ relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
+ else
+ throw Error("Unsupported checker.key-locator.hyper-relation.h-relation: " + hRelation);
+
+ try {
+ return shared_ptr<HyperKeyLocatorNameChecker>
+ (new HyperKeyLocatorNameChecker(pRegex, pExpand,
+ kRegex, kExpand,
+ relation));
+ }
+ catch (ndn::Regex::Error& e) {
+ throw Error("Invalid regex for key-locator.hyper-relation");
+ }
+ }
+ else
+ throw Error("Unsupported checker.key-locator");
+}
+
+} // namespace conf
+} // namespace nsl
diff --git a/core/conf/key-locator-checker.hpp b/core/conf/key-locator-checker.hpp
new file mode 100644
index 0000000..921faa2
--- /dev/null
+++ b/core/conf/key-locator-checker.hpp
@@ -0,0 +1,127 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#ifndef NSL_CONF_KEY_LOCATOR_CHECKER_HPP
+#define NSL_CONF_KEY_LOCATOR_CHECKER_HPP
+
+#include "common.hpp"
+#include "config.hpp"
+#include <ndn-cxx/util/regex.hpp>
+
+namespace nsl {
+namespace conf {
+
+class KeyLocatorCheckerFactory;
+
+/**
+ * @brief KeyLocatorChecker is one of the classes used by ValidatorConfig.
+ *
+ * The ValidatorConfig class consists of a set of rules.
+ * The KeyLocatorChecker class is part of a rule and is used to check if the KeyLocator field of a
+ * packet satisfy the requirements.
+ */
+
+
+class KeyLocatorChecker
+{
+public:
+ enum Relation {
+ RELATION_EQUAL,
+ RELATION_IS_PREFIX_OF,
+ RELATION_IS_STRICT_PREFIX_OF
+ };
+
+ virtual
+ ~KeyLocatorChecker();
+
+ bool
+ check(const Data& data, const KeyLocator& keyLocator, std::string& failInfo);
+
+protected:
+ virtual bool
+ check(const Name& packetName, const KeyLocator& keyLocator, std::string& failInfo) = 0;
+
+ bool
+ checkRelation(const Relation& relation, const Name& name1, const Name& name2);
+};
+
+class RelationKeyLocatorNameChecker : public KeyLocatorChecker
+{
+public:
+ RelationKeyLocatorNameChecker(const Name& name, const KeyLocatorChecker::Relation& relation);
+
+protected:
+ virtual bool
+ check(const Name& packetName, const KeyLocator& keyLocator, std::string& failInfo);
+
+private:
+ Name m_name;
+ KeyLocatorChecker::Relation m_relation;
+};
+
+class RegexKeyLocatorNameChecker : public KeyLocatorChecker
+{
+public:
+ explicit
+ RegexKeyLocatorNameChecker(const ndn::Regex& regex);
+
+protected:
+ virtual bool
+ check(const Name& packetName, const KeyLocator& keyLocator, std::string& failInfo);
+
+private:
+ ndn::Regex m_regex;
+};
+
+class HyperKeyLocatorNameChecker : public KeyLocatorChecker
+{
+public:
+ HyperKeyLocatorNameChecker(const std::string& pExpr, const std::string pExpand,
+ const std::string& kExpr, const std::string kExpand,
+ const Relation& hyperRelation);
+
+protected:
+ virtual bool
+ check(const Name& packetName, const KeyLocator& keyLocator, std::string& failInfo);
+
+private:
+ shared_ptr<ndn::Regex> m_hyperPRegex;
+ shared_ptr<ndn::Regex> m_hyperKRegex;
+ Relation m_hyperRelation;
+};
+
+
+class KeyLocatorCheckerFactory
+{
+public:
+ static shared_ptr<KeyLocatorChecker>
+ create(const ConfigSection& configSection);
+
+private:
+ static shared_ptr<KeyLocatorChecker>
+ createKeyLocatorNameChecker(const ConfigSection& configSection);
+};
+
+
+} // namespace conf
+} // namespace nsl
+
+#endif // NSL_CONF_KEY_LOCATOR_CHECKER_HPP
diff --git a/core/conf/rule.cpp b/core/conf/rule.cpp
new file mode 100644
index 0000000..a4b571f
--- /dev/null
+++ b/core/conf/rule.cpp
@@ -0,0 +1,81 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#include "rule.hpp"
+
+namespace nsl {
+namespace conf {
+
+Rule::Rule(const std::string& id)
+ : m_id(id)
+{
+}
+
+Rule::~Rule()
+{
+}
+
+const std::string&
+Rule::getId()
+{
+ return m_id;
+}
+
+void
+Rule::addFilter(const shared_ptr<Filter>& filter)
+{
+ m_filters.push_back(filter);
+}
+
+void
+Rule::addChecker(const shared_ptr<Checker>& checker)
+{
+ m_checkers.push_back(checker);
+}
+
+bool
+Rule::match(const Data& data)
+{
+ if (m_filters.empty())
+ return true;
+
+ for (auto& filter : m_filters) {
+ if (!filter->match(data))
+ return false;
+ }
+
+ return true;
+}
+
+bool
+Rule::check(const Data& data)
+{
+ for (auto& checker : m_checkers) {
+ bool result = checker->check(data);
+ if (result)
+ return result;
+ }
+
+ return false;
+}
+
+} // namespace conf
+} // namespace nsl
diff --git a/core/conf/rule.hpp b/core/conf/rule.hpp
new file mode 100644
index 0000000..5ec229f
--- /dev/null
+++ b/core/conf/rule.hpp
@@ -0,0 +1,73 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#ifndef NSL_CONF_RULE_HPP
+#define NSL_CONF_RULE_HPP
+
+#include "filter.hpp"
+#include "checker.hpp"
+
+namespace nsl {
+namespace conf {
+
+class Rule
+{
+public:
+ explicit
+ Rule(const std::string& id);
+
+ virtual
+ ~Rule();
+
+ const std::string&
+ getId();
+
+ void
+ addFilter(const shared_ptr<Filter>& filter);
+
+ void
+ addChecker(const shared_ptr<Checker>& checker);
+
+ bool
+ match(const Data& data);
+
+ /**
+ * @brief check if data satisfies certain condition
+ *
+ * @param packet The packet
+ * @return false if data is immediately invalid
+ */
+ bool
+ check(const Data& data);
+
+private:
+ typedef std::vector<shared_ptr<Filter> > FilterList;
+ typedef std::vector<shared_ptr<Checker> > CheckerList;
+
+ std::string m_id;
+ FilterList m_filters;
+ CheckerList m_checkers;
+};
+
+} // namespace conf
+} // namespace nsl
+
+#endif // NSL_CONF_RULE_HPP
diff --git a/core/policy-checker.cpp b/core/policy-checker.cpp
new file mode 100644
index 0000000..b0d6531
--- /dev/null
+++ b/core/policy-checker.cpp
@@ -0,0 +1,170 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#include "policy-checker.hpp"
+#include <ndn-cxx/util/time.hpp>
+#include <ndn-cxx/security/validator.hpp>
+#include <boost/algorithm/string.hpp>
+
+namespace nsl {
+
+using ndn::time::system_clock;
+
+PolicyChecker::PolicyChecker()
+{
+}
+
+void
+PolicyChecker::reset()
+{
+ m_dataRules.clear();
+}
+
+void
+PolicyChecker::loadPolicy(const conf::ConfigSection& configSection)
+{
+ reset();
+
+ for (const auto& section : configSection) {
+ if (boost::iequals(section.first, "rule")) {
+ onConfigRule(section.second);
+ }
+ else
+ throw Error("Error in loading policy checker: unrecognized section " + section.first);
+ }
+}
+
+void
+PolicyChecker::onConfigRule(const conf::ConfigSection& section)
+{
+ using namespace nsl::conf;
+
+ auto it = section.begin();
+
+ // Get rule.id
+ if (it == section.end() || !boost::iequals(it->first, "id"))
+ throw Error("Expect <rule.id>");
+
+ std::string ruleId = it->second.data();
+ it++;
+
+ // Get rule.for
+ if (it == section.end() || !boost::iequals(it->first, "for"))
+ throw Error("Expect <rule.for> in rule: " + ruleId);
+
+ std::string usage = it->second.data();
+ it++;
+
+ 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 (; it != section.end(); it++) {
+ if (!boost::iequals(it->first, "filter")) {
+ if (boost::iequals(it->first, "checker"))
+ break;
+ throw Error("Expect <rule.filter> in rule: " + ruleId);
+ }
+
+ filters.push_back(FilterFactory::create(it->second));
+ continue;
+ }
+
+ // Get rule.checker(s)
+ std::vector<shared_ptr<Checker> > checkers;
+ for (; it != section.end(); it++) {
+ if (!boost::iequals(it->first, "checker"))
+ throw Error("Expect <rule.checker> in rule: " + ruleId);
+
+ checkers.push_back(CheckerFactory::create(it->second));
+ continue;
+ }
+
+ // Check other stuff
+ if (it != section.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) {
+ auto rule = make_shared<conf::Rule>(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);
+ }
+}
+
+bool
+PolicyChecker::check(const Timestamp& dataTimestamp, const Data& data,
+ const Timestamp& keyTimestamp, const ndn::IdentityCertificate& cert)
+{
+ system_clock::TimePoint dataTs((time::seconds(dataTimestamp)));
+ system_clock::TimePoint keyTs((time::seconds(keyTimestamp)));
+ system_clock::TimePoint endTs = cert.getNotAfter();
+ system_clock::TimePoint startTs = cert.getNotBefore();
+
+ if (dataTs > endTs || dataTs < keyTs || dataTs < startTs)
+ return false;
+
+ if (!checkRule(data))
+ return false;
+
+ Name keyLocatorName;
+ try {
+ keyLocatorName = data.getSignature().getKeyLocator().getName();
+ }
+ catch (tlv::Error&) {
+ return false;
+ }
+
+ if (!keyLocatorName.isPrefixOf(cert.getName()))
+ return false;
+
+ if (!ndn::Validator::verifySignature(data, cert.getPublicKeyInfo()))
+ return false;
+
+ return true;
+}
+
+bool
+PolicyChecker::checkRule(const Data& data)
+{
+ for (auto& rule : m_dataRules) {
+ if (rule->match(data)) {
+ return rule->check(data);
+ }
+ }
+
+ return false;
+}
+
+
+} // namespace nsl
diff --git a/core/policy-checker.hpp b/core/policy-checker.hpp
new file mode 100644
index 0000000..8eea548
--- /dev/null
+++ b/core/policy-checker.hpp
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#ifndef NSL_CORE_POLICY_CHECKER_HPP
+#define NSL_CORE_POLICY_CHECKER_HPP
+
+#include "common.hpp"
+#include "db.hpp"
+#include "util/non-negative-integer.hpp"
+#include "conf/config.hpp"
+#include "conf/rule.hpp"
+#include <ndn-cxx/security/identity-certificate.hpp>
+
+
+namespace nsl {
+
+class PolicyChecker
+{
+public:
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+public:
+ PolicyChecker();
+
+ void
+ reset();
+
+ void
+ loadPolicy(const conf::ConfigSection& policy);
+
+ bool
+ check(const Timestamp& dataTimestamp, const Data& data,
+ const Timestamp& keyTimestamp, const ndn::IdentityCertificate& cert);
+private:
+
+ void
+ onConfigRule(const conf::ConfigSection& section);
+
+ bool
+ checkRule(const Data& data);
+
+private:
+ typedef std::vector<shared_ptr<conf::Rule>> DataRuleList;
+
+ DataRuleList m_dataRules;
+};
+
+} // namespace nsl
+
+#endif // NSL_CORE_POLICY_CHECKER_HPP
diff --git a/tests/core/identity-fixture.hpp b/tests/core/identity-fixture.hpp
new file mode 100644
index 0000000..3ea68f6
--- /dev/null
+++ b/tests/core/identity-fixture.hpp
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#ifndef NSL_TESTS_IDENTITY_FIXTURE_HPP
+#define NSL_TESTS_IDENTITY_FIXTURE_HPP
+
+#include "unit-test-time-fixture.hpp"
+#include <ndn-cxx/security/key-chain.hpp>
+#include <vector>
+
+#include <boost/filesystem.hpp>
+
+namespace nsl {
+namespace tests {
+
+class IdentityFixture : public UnitTestTimeFixture
+{
+public:
+ IdentityFixture()
+ : m_keyChainTmpPath(boost::filesystem::path(TEST_KEYCHAIN_PATH) / "IdentityFixture")
+ , m_keyChain(std::string("pib-sqlite3:").append(m_keyChainTmpPath.string()),
+ std::string("tpm-file:").append(m_keyChainTmpPath.string()))
+ {
+ }
+
+ ~IdentityFixture()
+ {
+ for (const auto& identity : m_identities) {
+ m_keyChain.deleteIdentity(identity);
+ }
+
+ boost::filesystem::remove_all(m_keyChainTmpPath);
+ }
+ /// @brief add identity, return true if succeed.
+ bool
+ addIdentity(const Name& identity,
+ const ndn::KeyParams& params = ndn::KeyChain::DEFAULT_KEY_PARAMS)
+ {
+ try {
+ m_keyChain.createIdentity(identity, params);
+ m_identities.push_back(identity);
+ return true;
+ }
+ catch (std::runtime_error&) {
+ return false;
+ }
+ }
+
+protected:
+ boost::filesystem::path m_keyChainTmpPath;
+ ndn::KeyChain m_keyChain;
+ std::vector<Name> m_identities;
+};
+
+} // namespace tests
+} // namespace nsl
+
+#endif // NSL_TESTS_IDENTITY_FIXTURE_HPP
diff --git a/tests/core/policy-checker.t.cpp b/tests/core/policy-checker.t.cpp
new file mode 100644
index 0000000..75c2ef4
--- /dev/null
+++ b/tests/core/policy-checker.t.cpp
@@ -0,0 +1,193 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#include "policy-checker.hpp"
+#include "identity-fixture.hpp"
+#include <boost/property_tree/info_parser.hpp>
+
+#include "boost-test.hpp"
+
+namespace nsl {
+namespace tests {
+
+BOOST_FIXTURE_TEST_SUITE(TestPolicyChecker, IdentityFixture)
+
+BOOST_AUTO_TEST_CASE(TimeCheck)
+{
+ const std::string CONFIG =
+ "rule \n"
+ "{ \n"
+ " id \"Simple Rule\" \n"
+ " for data \n"
+ " checker \n"
+ " { \n"
+ " type customized \n"
+ " sig-type rsa-sha256 \n"
+ " key-locator \n"
+ " { \n"
+ " type name \n"
+ " hyper-relation \n"
+ " { \n"
+ " k-regex ^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$ \n"
+ " k-expand \\\\1\\\\2 \n"
+ " h-relation is-strict-prefix-of \n"
+ " p-regex ^(<>*)$ \n"
+ " p-expand \\\\1 \n"
+ " } \n"
+ " } \n"
+ " } \n"
+ "} \n";
+
+ std::istringstream input(CONFIG);
+ conf::ConfigSection policy;
+ BOOST_REQUIRE_NO_THROW(boost::property_tree::read_info(input, policy));
+
+ PolicyChecker policyChecker;
+ policyChecker.loadPolicy(policy);
+
+ Name identity("/test/id");
+ addIdentity(identity);
+ Name selfSignedCertName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
+ auto selfSignedCert = m_keyChain.getCertificate(selfSignedCertName);
+
+ time::system_clock::TimePoint notBefore = time::system_clock::now();
+ time::system_clock::TimePoint notAfter = time::system_clock::now() + time::seconds(10);
+ std::vector<ndn::CertificateSubjectDescription> subDesc;
+
+ auto unsignedCert =
+ m_keyChain.prepareUnsignedIdentityCertificate(selfSignedCert->getPublicKeyName(),
+ selfSignedCert->getPublicKeyInfo(),
+ identity,
+ notBefore,
+ notAfter,
+ subDesc);
+
+ m_keyChain.sign(*unsignedCert, selfSignedCertName);
+ m_keyChain.addCertificate(*unsignedCert);
+
+ time::system_clock::TimePoint dataTs1 = time::system_clock::now() + time::seconds(5);
+ time::system_clock::TimePoint dataTs2 = time::system_clock::now() + time::seconds(1);
+ time::system_clock::TimePoint dataTs3 = time::system_clock::now() + time::seconds(15);
+ time::system_clock::TimePoint dataTs4 = time::system_clock::now() - time::seconds(1);
+ time::system_clock::TimePoint keyTs1 = time::system_clock::now() + time::seconds(2);
+ time::system_clock::TimePoint keyTs2 = time::system_clock::now() - time::seconds(2);
+ Timestamp dataTimestamp1 = time::toUnixTimestamp(dataTs1).count() / 1000;
+ Timestamp dataTimestamp2 = time::toUnixTimestamp(dataTs2).count() / 1000;
+ Timestamp dataTimestamp3 = time::toUnixTimestamp(dataTs3).count() / 1000;
+ Timestamp dataTimestamp4 = time::toUnixTimestamp(dataTs4).count() / 1000;
+ Timestamp keyTimestamp1 = time::toUnixTimestamp(keyTs1).count() / 1000;
+ Timestamp keyTimestamp2 = time::toUnixTimestamp(keyTs2).count() / 1000;
+
+ Data data("/test/id/data");
+ m_keyChain.sign(data, unsignedCert->getName());
+
+ BOOST_CHECK_EQUAL(policyChecker.check(dataTimestamp1, data, keyTimestamp1, *unsignedCert), true);
+ BOOST_CHECK_EQUAL(policyChecker.check(dataTimestamp2, data, keyTimestamp1, *unsignedCert), false);
+ BOOST_CHECK_EQUAL(policyChecker.check(dataTimestamp3, data, keyTimestamp1, *unsignedCert), false);
+ BOOST_CHECK_EQUAL(policyChecker.check(dataTimestamp4, data, keyTimestamp2, *unsignedCert), false);
+}
+
+BOOST_AUTO_TEST_CASE(RuleCheck)
+{
+ const std::string CONFIG =
+ "rule \n"
+ "{ \n"
+ " id \"Simple Rule\" \n"
+ " for data \n"
+ " checker \n"
+ " { \n"
+ " type customized \n"
+ " sig-type rsa-sha256 \n"
+ " key-locator \n"
+ " { \n"
+ " type name \n"
+ " hyper-relation \n"
+ " { \n"
+ " k-regex ^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$ \n"
+ " k-expand \\\\1\\\\2 \n"
+ " h-relation is-strict-prefix-of \n"
+ " p-regex ^(<>*)$ \n"
+ " p-expand \\\\1 \n"
+ " } \n"
+ " } \n"
+ " } \n"
+ "} \n";
+
+ std::istringstream input(CONFIG);
+ conf::ConfigSection policy;
+ BOOST_REQUIRE_NO_THROW(boost::property_tree::read_info(input, policy));
+
+ PolicyChecker policyChecker;
+ policyChecker.loadPolicy(policy);
+
+
+ Name identity("/test/id");
+ addIdentity(identity);
+ Name selfSignedCertName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
+ auto selfSignedCert = m_keyChain.getCertificate(selfSignedCertName);
+
+ time::system_clock::TimePoint notBefore = time::system_clock::now();
+ time::system_clock::TimePoint notAfter = time::system_clock::now() + time::seconds(10);
+ std::vector<ndn::CertificateSubjectDescription> subDesc;
+
+ auto unsignedCert =
+ m_keyChain.prepareUnsignedIdentityCertificate(selfSignedCert->getPublicKeyName(),
+ selfSignedCert->getPublicKeyInfo(),
+ identity,
+ notBefore,
+ notAfter,
+ subDesc);
+
+ m_keyChain.sign(*unsignedCert, selfSignedCertName);
+ m_keyChain.addCertificate(*unsignedCert);
+
+ time::system_clock::TimePoint dataTs1 = time::system_clock::now() + time::seconds(5);
+ time::system_clock::TimePoint keyTs1 = time::system_clock::now() + time::seconds(2);
+ Timestamp dataTimestamp1 = time::toUnixTimestamp(dataTs1).count() / 1000;
+ Timestamp keyTimestamp1 = time::toUnixTimestamp(keyTs1).count() / 1000;
+
+
+ Data data1("/test/id/data");
+ m_keyChain.sign(data1, unsignedCert->getName());
+ BOOST_CHECK_EQUAL(policyChecker.check(dataTimestamp1, data1, keyTimestamp1, *unsignedCert),
+ true);
+
+ Data data2("/test/id");
+ m_keyChain.sign(data2, unsignedCert->getName());
+ BOOST_CHECK_EQUAL(policyChecker.check(dataTimestamp1, data2, keyTimestamp1, *unsignedCert),
+ false);
+
+ Data data3("/test/wrong");
+ m_keyChain.sign(data3, unsignedCert->getName());
+ BOOST_CHECK_EQUAL(policyChecker.check(dataTimestamp1, data3, keyTimestamp1, *unsignedCert),
+ false);
+
+ Data data4("/test");
+ m_keyChain.sign(data4, unsignedCert->getName());
+ BOOST_CHECK_EQUAL(policyChecker.check(dataTimestamp1, data4, keyTimestamp1, *unsignedCert),
+ false);
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nsl
diff --git a/tests/core/unit-test-time-fixture.hpp b/tests/core/unit-test-time-fixture.hpp
new file mode 100644
index 0000000..e70d66e
--- /dev/null
+++ b/tests/core/unit-test-time-fixture.hpp
@@ -0,0 +1,69 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#ifndef NSL_TESTS_UNIT_TESTS_UNIT_TEST_TIME_FIXTURE_HPP
+#define NSL_TESTS_UNIT_TESTS_UNIT_TEST_TIME_FIXTURE_HPP
+
+#include <ndn-cxx/util/time-unit-test-clock.hpp>
+
+#include <boost/asio.hpp>
+
+namespace nsl {
+namespace tests {
+
+class UnitTestTimeFixture
+{
+public:
+ UnitTestTimeFixture()
+ : steadyClock(make_shared<ndn::time::UnitTestSteadyClock>())
+ , systemClock(make_shared<ndn::time::UnitTestSystemClock>())
+ {
+ time::setCustomClocks(steadyClock, systemClock);
+ }
+
+ ~UnitTestTimeFixture()
+ {
+ time::setCustomClocks(nullptr, nullptr);
+ }
+
+ void
+ advanceClocks(const time::nanoseconds& tick, size_t nTicks = 1)
+ {
+ for (size_t i = 0; i < nTicks; ++i) {
+ steadyClock->advance(tick);
+ systemClock->advance(tick);
+
+ if (io.stopped())
+ io.reset();
+ io.poll();
+ }
+ }
+
+public:
+ shared_ptr<ndn::time::UnitTestSteadyClock> steadyClock;
+ shared_ptr<ndn::time::UnitTestSystemClock> systemClock;
+ boost::asio::io_service io;
+};
+
+} // namespace tests
+} // namespace nsl
+
+#endif // NSL_TESTS_UNIT_TESTS_UNIT_TEST_TIME_FIXTURE_HPP