security: Add configuration based validator
configuration file format can be found at: http://redmine.named-data.net/projects/ndn-cpp-dev/wiki/CommandValidatorConf
Change-Id: Icc2725f349aed7513f35f2cccdcd4463fadeef31
diff --git a/src/security/conf/checker.hpp b/src/security/conf/checker.hpp
new file mode 100644
index 0000000..1ec2323
--- /dev/null
+++ b/src/security/conf/checker.hpp
@@ -0,0 +1,481 @@
+/* -*- 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
diff --git a/src/security/conf/common.hpp b/src/security/conf/common.hpp
new file mode 100644
index 0000000..ba68e2a
--- /dev/null
+++ b/src/security/conf/common.hpp
@@ -0,0 +1,34 @@
+/* -*- 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_COMMON_HPP
+#define NDN_SECURITY_CONF_COMMON_HPP
+
+#include <string>
+#include <boost/property_tree/ptree.hpp>
+
+namespace ndn {
+namespace security {
+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 security
+} // namespace ndn
+
+#endif // NDN_SECURITY_CONF_COMMON_HPP
diff --git a/src/security/conf/filter.hpp b/src/security/conf/filter.hpp
new file mode 100644
index 0000000..1db7498
--- /dev/null
+++ b/src/security/conf/filter.hpp
@@ -0,0 +1,224 @@
+/* -*- 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_FILTER_HPP
+#define NDN_SECURITY_CONF_FILTER_HPP
+
+#include "../../common.hpp"
+#include "../../data.hpp"
+#include "../../interest.hpp"
+#include "../../util/regex.hpp"
+#include <boost/algorithm/string.hpp>
+
+#include "common.hpp"
+
+namespace ndn {
+namespace security {
+namespace conf {
+
+class Filter
+{
+public:
+ virtual
+ ~Filter()
+ {
+ }
+
+ virtual bool
+ match(const Data& data) = 0;
+
+ virtual bool
+ match(const Interest& interest) = 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)
+ : m_name(name)
+ , m_relation(relation)
+ {
+ }
+
+ virtual
+ ~RelationNameFilter()
+ {
+ }
+
+ virtual bool
+ match(const Data& data)
+ {
+ return match(data.getName());
+ }
+
+ virtual bool
+ match(const Interest& interest)
+ {
+ if (interest.getName().size() < 2)
+ return false;
+
+ Name signedName = interest.getName().getPrefix(-2);
+ return match(signedName);
+ }
+
+private:
+ bool
+ match(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 != name);
+ default:
+ return false;
+ }
+ }
+
+private:
+ Name m_name;
+ Relation m_relation;
+};
+
+class RegexNameFilter : public Filter
+{
+public:
+ explicit
+ RegexNameFilter(const Regex& regex)
+ : m_regex(regex)
+ {
+ }
+
+ virtual
+ ~RegexNameFilter()
+ {
+ }
+
+ virtual bool
+ match(const Data& data)
+ {
+ return m_regex.match(data.getName());
+ }
+
+ virtual bool
+ match(const Interest& interest)
+ {
+ if (interest.getName().size() < 2)
+ return false;
+
+ Name signedName = interest.getName().getPrefix(-2);
+ return m_regex.match(signedName);
+ }
+
+private:
+ Regex m_regex;
+};
+
+class FilterFactory
+{
+public:
+ static shared_ptr<Filter>
+ 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);
+ }
+private:
+ static shared_ptr<Filter>
+ 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>(boost::cref(name),
+ boost::cref(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 (const Regex::Error& e)
+ {
+ throw Error("Wrong filter.regex: " + regexString);
+ }
+ }
+ else
+ throw Error("Wrong filter(name) properties");
+ }
+};
+
+} // namespace conf
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_CONF_FILTER_HPP
diff --git a/src/security/conf/key-locator-checker.hpp b/src/security/conf/key-locator-checker.hpp
new file mode 100644
index 0000000..0f667f7
--- /dev/null
+++ b/src/security/conf/key-locator-checker.hpp
@@ -0,0 +1,362 @@
+/* -*- 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_KEY_LOCATOR_CHECKER_HPP
+#define NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP
+
+#include "../../common.hpp"
+#include "../../data.hpp"
+#include "../../interest.hpp"
+#include <boost/algorithm/string.hpp>
+
+#include "common.hpp"
+
+namespace ndn {
+namespace security {
+namespace conf {
+
+class KeyLocatorCheckerFactory;
+
+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)
+ {
+ return check(data.getName(), keyLocator, failInfo);
+ }
+
+ bool
+ check(const Interest& interest,
+ const KeyLocator& keyLocator,
+ std::string& failInfo)
+ {
+ if (interest.getName().size() < 2)
+ {
+ failInfo = "No Signature";
+ return false;
+ }
+
+ Name signedName = interest.getName().getPrefix(-2);
+ return check(signedName, keyLocator, 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)
+ {
+ 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;
+ }
+ }
+};
+
+class RelationKeyLocatorNameChecker : public KeyLocatorChecker
+{
+public:
+ RelationKeyLocatorNameChecker(const Name& name,
+ const KeyLocatorChecker::Relation& relation)
+ : m_name(name)
+ , m_relation(relation)
+ {
+ }
+
+protected:
+ virtual bool
+ 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 (const KeyLocator::Error& e)
+ {
+ failInfo = "KeyLocator does not have name";
+ return false;
+ }
+ }
+
+private:
+ Name m_name;
+ KeyLocatorChecker::Relation m_relation;
+};
+
+class RegexKeyLocatorNameChecker : public KeyLocatorChecker
+{
+public:
+ RegexKeyLocatorNameChecker(const Regex& regex)
+ : m_regex(regex)
+ {
+ }
+
+protected:
+ virtual bool
+ 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 (const KeyLocator::Error& e)
+ {
+ failInfo = "KeyLocator does not have name";
+ return false;
+ }
+ }
+
+private:
+ 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)
+ : m_hyperPRegex(new Regex(pExpr, pExpand))
+ , m_hyperKRegex(new Regex(kExpr, kExpand))
+ , m_hyperRelation(hyperRelation)
+ {
+ }
+
+protected:
+ virtual bool
+ 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 (const KeyLocator::Error& e)
+ {
+ failInfo = "KeyLocator does not have name";
+ return false;
+ }
+
+ }
+
+private:
+ shared_ptr<Regex> m_hyperPRegex;
+ shared_ptr<Regex> m_hyperKRegex;
+ Relation m_hyperRelation;
+};
+
+
+class KeyLocatorCheckerFactory
+{
+public:
+ static shared_ptr<KeyLocatorChecker>
+ create(const ConfigSection& configSection, const std::string& filename)
+ {
+ 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, filename);
+ else
+ throw Error("Unsupported checker.key-locator.type: " + type);
+ }
+
+private:
+ static shared_ptr<KeyLocatorChecker>
+ createKeyLocatorNameChecker(const ConfigSection& configSection,
+ const std::string& filename)
+ {
+ 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 (const 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 (const Regex::Error& e)
+ {
+ throw Error("Invalid regex for key-locator.hyper-relation");
+ }
+ }
+ else
+ throw Error("Unsupported checker.key-locator");
+ }
+};
+
+
+} // namespace conf
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP
diff --git a/src/security/conf/rule.hpp b/src/security/conf/rule.hpp
new file mode 100644
index 0000000..560c440
--- /dev/null
+++ b/src/security/conf/rule.hpp
@@ -0,0 +1,106 @@
+/* -*- 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_RULE_HPP
+#define NDN_SECURITY_CONF_RULE_HPP
+
+#include "filter.hpp"
+#include "checker.hpp"
+
+
+namespace ndn {
+namespace security {
+namespace conf {
+
+template<class Packet>
+class Rule
+{
+public:
+ Rule(const std::string& id)
+ : m_id(id)
+ {
+ }
+
+ virtual
+ ~Rule()
+ {
+ }
+
+ const std::string&
+ getId()
+ {
+ return m_id;
+ }
+
+ void
+ addFilter(const shared_ptr<Filter>& filter)
+ {
+ m_filters.push_back(filter);
+ }
+
+ void
+ addChecker(const shared_ptr<Checker>& checker)
+ {
+ m_checkers.push_back(checker);
+ }
+
+ bool
+ match(const Packet& packet)
+ {
+ if (m_filters.empty())
+ return true;
+
+ for (FilterList::iterator it = m_filters.begin();
+ it != m_filters.end(); it++)
+ {
+ if (!(*it)->match(packet))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @brief check if packet satisfies certain condition
+ *
+ * @param packet The packet
+ * @param onValidated Callback function which is called when packet is immediately valid
+ * @param onValidationFailed Call function which is called when packet is immediately invalid
+ * @return -1 if packet is immediately invalid (onValidationFailed has been called)
+ * 1 if packet is immediately valid (onValidated has been called)
+ * 0 if further signature verification is needed.
+ */
+ template<class ValidatedCallback, class ValidationFailureCallback>
+ int8_t
+ check(const Packet& packet,
+ const ValidatedCallback& onValidated,
+ const ValidationFailureCallback& onValidationFailed)
+ {
+ for (CheckerList::iterator it = m_checkers.begin();
+ it != m_checkers.end(); it++)
+ {
+ int8_t result = (*it)->check(packet, onValidated, onValidationFailed);
+ if (result >= 0)
+ return result;
+ }
+ return -1;
+ }
+
+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 security
+} // namespace ndn
+
+#endif // NDN_SECURITY_CONF_RULE_HPP
diff --git a/src/security/validator-config.cpp b/src/security/validator-config.cpp
new file mode 100644
index 0000000..2085daf
--- /dev/null
+++ b/src/security/validator-config.cpp
@@ -0,0 +1,352 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "validator-config.hpp"
+#include "certificate-cache-ttl.hpp"
+#include "../util/io.hpp"
+
+#include <boost/filesystem.hpp>
+#include <boost/property_tree/info_parser.hpp>
+#include <boost/algorithm/string.hpp>
+
+namespace ndn {
+
+const shared_ptr<CertificateCache> ValidatorConfig::DEFAULT_CERTIFICATE_CACHE;
+
+ValidatorConfig::ValidatorConfig(shared_ptr<Face> face,
+ shared_ptr<CertificateCache> certificateCache,
+ const int stepLimit)
+ : Validator(face)
+ , m_stepLimit(stepLimit)
+ , m_certificateCache(certificateCache)
+{
+ if (!static_cast<bool>(face))
+ throw Error("Face is not set!");
+
+ if (!static_cast<bool>(m_certificateCache))
+ m_certificateCache = make_shared<CertificateCacheTtl>(m_face->ioService());
+}
+
+void
+ValidatorConfig::load(const std::string& filename)
+{
+ std::ifstream inputFile;
+ inputFile.open(filename.c_str());
+ if (!inputFile.good() || !inputFile.is_open())
+ {
+ std::string msg = "Failed to read configuration file: ";
+ msg += filename;
+ throw security::conf::Error(msg);
+ }
+ load(inputFile, filename);
+ inputFile.close();
+}
+
+void
+ValidatorConfig::load(const std::string& input, const std::string& filename)
+{
+ std::istringstream inputStream(input);
+ load(inputStream, filename);
+}
+
+
+void
+ValidatorConfig::load(std::istream& input, const std::string& filename)
+{
+ security::conf::ConfigSection tree;
+ try
+ {
+ boost::property_tree::read_info(input, tree);
+ }
+ catch (const boost::property_tree::info_parser_error& error)
+ {
+ std::stringstream msg;
+ msg << "Failed to parse configuration file";
+ msg << " " << filename;
+ msg << " " << error.message() << " line " << error.line();
+ throw security::conf::Error(msg.str());
+ }
+
+ process(tree, filename);
+}
+
+void
+ValidatorConfig::process(const security::conf::ConfigSection& configSection,
+ const std::string& filename)
+{
+ BOOST_ASSERT(!filename.empty());
+
+ if (configSection.begin() == configSection.end())
+ {
+ std::string msg = "Error processing configuration file";
+ msg += ": ";
+ msg += filename;
+ msg += " no data";
+ throw security::conf::Error(msg);
+ }
+
+ for (security::conf::ConfigSection::const_iterator i = configSection.begin();
+ i != configSection.end(); ++i)
+ {
+ const std::string& sectionName = i->first;
+ const security::conf::ConfigSection& section = i->second;
+
+ if (boost::iequals(sectionName, "rule"))
+ {
+ onConfigRule(section, filename);
+ }
+ else if (boost::iequals(sectionName, "trust-anchor"))
+ {
+ onConfigTrustAnchor(section, filename);
+ }
+ else
+ {
+ std::string msg = "Error processing configuration file";
+ msg += " ";
+ msg += filename;
+ msg += " unrecognized section: " + sectionName;
+ throw security::conf::Error(msg);
+ }
+ }
+}
+
+void
+ValidatorConfig::onConfigRule(const security::conf::ConfigSection& configSection,
+ const std::string& filename)
+{
+ using namespace ndn::security::conf;
+
+ ConfigSection::const_iterator propertyIt = configSection.begin();
+
+ // Get rule.id
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "id"))
+ throw Error("Expect <rule.id>!");
+
+ std::string ruleId = propertyIt->second.data();
+ propertyIt++;
+
+ // Get rule.for
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first,"for"))
+ throw Error("Expect <rule.for> in rule: " + ruleId + "!");
+
+ std::string usage = propertyIt->second.data();
+ propertyIt++;
+
+ bool isForData;
+ if (boost::iequals(usage, "data"))
+ isForData = true;
+ else if (boost::iequals(usage, "interest"))
+ isForData = false;
+ else
+ throw Error("Unrecognized <rule.for>: " + usage
+ + " in rule: " + ruleId);
+
+ // Get rule.filter(s)
+ std::vector<shared_ptr<Filter> > filters;
+ for (; propertyIt != configSection.end(); propertyIt++)
+ {
+ if (!boost::iequals(propertyIt->first, "filter"))
+ {
+ if (boost::iequals(propertyIt->first, "checker"))
+ break;
+ throw Error("Expect <rule.filter> in rule: " + ruleId);
+ }
+
+ filters.push_back(FilterFactory::create(propertyIt->second));
+ continue;
+ }
+
+ // Get rule.checker(s)
+ std::vector<shared_ptr<Checker> > checkers;
+ for (; propertyIt != configSection.end(); propertyIt++)
+ {
+ if (!boost::iequals(propertyIt->first, "checker"))
+ throw Error("Expect <rule.checker> in rule: " + ruleId);
+
+ checkers.push_back(CheckerFactory::create(propertyIt->second, filename));
+ continue;
+ }
+
+ // Check other stuff
+ if (propertyIt != configSection.end())
+ throw Error("Expect the end of rule: " + ruleId);
+
+ if (checkers.size() == 0)
+ throw Error("No <rule.checker> is specified in rule: " + ruleId);
+
+ if (isForData)
+ {
+ shared_ptr<DataRule> rule(new DataRule(ruleId));
+ for (size_t i = 0; i < filters.size(); i++)
+ rule->addFilter(filters[i]);
+ for (size_t i = 0; i < checkers.size(); i++)
+ rule->addChecker(checkers[i]);
+
+ m_dataRules.push_back(rule);
+ }
+ else
+ {
+ shared_ptr<InterestRule> rule(new InterestRule(ruleId));
+ for (size_t i = 0; i < filters.size(); i++)
+ rule->addFilter(filters[i]);
+ for (size_t i = 0; i < checkers.size(); i++)
+ rule->addChecker(checkers[i]);
+
+ m_interestRules.push_back(rule);
+ }
+}
+
+void
+ValidatorConfig::onConfigTrustAnchor(const security::conf::ConfigSection& configSection,
+ const std::string& filename)
+{
+ using namespace ndn::security::conf;
+ using namespace boost::filesystem;
+
+ ConfigSection::const_iterator propertyIt = configSection.begin();
+
+ // Get trust-anchor.type
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
+ throw Error("Expect <trust-anchor.type>!");
+
+ std::string type = propertyIt->second.data();
+ propertyIt++;
+
+ if (boost::iequals(type, "file"))
+ {
+ // Get trust-anchor.file
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first,"file-name"))
+ throw Error("Expect <trust-anchor.file-name>!");
+
+ std::string file = propertyIt->second.data();
+ propertyIt++;
+
+ // Check other stuff
+ if (propertyIt != configSection.end())
+ throw Error("Expect the end of trust-anchor!");
+
+ path certfilePath = absolute(file, path(filename).parent_path());
+ shared_ptr<IdentityCertificate> idCert =
+ io::load<IdentityCertificate>(certfilePath.string());
+
+ if (static_cast<bool>(idCert))
+ {
+ BOOST_ASSERT(idCert->getName().size() >= 1);
+ m_anchors[idCert->getName().getPrefix(-1)] = idCert;
+ }
+ else
+ throw Error("Cannot read certificate from file: " +
+ certfilePath.native());
+
+ return;
+ }
+ else if (boost::iequals(type, "base64"))
+ {
+ // Get trust-anchor.base64-string
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "base64-string"))
+ throw Error("Expect <trust-anchor.base64-string>!");
+
+ std::stringstream ss(propertyIt->second.data());
+ propertyIt++;
+
+ // Check other stuff
+ if (propertyIt != configSection.end())
+ throw Error("Expect the end of trust-anchor!");
+
+ shared_ptr<IdentityCertificate> idCert = io::load<IdentityCertificate>(ss);
+
+ if (static_cast<bool>(idCert))
+ {
+ BOOST_ASSERT(idCert->getName().size() >= 1);
+ m_anchors[idCert->getName().getPrefix(-1)] = idCert;
+ }
+ else
+ throw Error("Cannot decode certificate from base64-string");
+
+ return;
+ }
+ else
+ throw Error("Unsupported trust-anchor.type: " + type);
+}
+
+void
+ValidatorConfig::checkPolicy(const Data& data,
+ int stepCount,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps)
+{
+ if (m_stepLimit == stepCount)
+ return onValidationFailed(data.shared_from_this(),
+ "Maximum steps of validation reached");
+
+ bool isMatched = false;
+ int8_t checkResult = -1;
+
+ for (DataRuleList::iterator it = m_dataRules.begin();
+ it != m_dataRules.end(); it++)
+ {
+ if ((*it)->match(data))
+ {
+ isMatched = true;
+ checkResult = (*it)->check(data, onValidated, onValidationFailed);
+ break;
+ }
+ }
+
+ if (!isMatched)
+ return onValidationFailed(data.shared_from_this(), "No rule matched!");
+
+ if (checkResult == 0)
+ {
+ const Signature& signature = data.getSignature();
+ checkSignature(data, signature, stepCount,
+ onValidated, onValidationFailed, nextSteps);
+ }
+}
+
+void
+ValidatorConfig::checkPolicy(const Interest& interest,
+ int stepCount,
+ const OnInterestValidated& onValidated,
+ const OnInterestValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps)
+{
+ if (m_stepLimit == stepCount)
+ return onValidationFailed(interest.shared_from_this(),
+ "Maximum steps of validation reached");
+
+ bool isMatched = false;
+ int8_t checkResult = -1;
+
+ for (InterestRuleList::iterator it = m_interestRules.begin();
+ it != m_interestRules.end(); it++)
+ {
+ if ((*it)->match(interest))
+ {
+ isMatched = true;
+ checkResult = (*it)->check(interest, onValidated, onValidationFailed);
+ break;
+ }
+ }
+
+ if (!isMatched)
+ return onValidationFailed(interest.shared_from_this(), "No rule matched!");
+
+ if (checkResult == 0)
+ {
+ const Name& interestName = interest.getName();
+ Name signedName = interestName.getPrefix(-2);
+ Signature signature(interestName[-2].blockFromValue(),
+ interestName[-1].blockFromValue());
+
+ checkSignature(interest, signature, stepCount,
+ onValidated, onValidationFailed, nextSteps);
+ }
+}
+
+
+} // namespace ndn
diff --git a/src/security/validator-config.hpp b/src/security/validator-config.hpp
new file mode 100644
index 0000000..acc85f5
--- /dev/null
+++ b/src/security/validator-config.hpp
@@ -0,0 +1,224 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_SECURITY_VALIDATOR_CONFIG_HPP
+#define NDN_SECURITY_VALIDATOR_CONFIG_HPP
+
+#include "validator.hpp"
+#include "certificate-cache.hpp"
+#include "conf/rule.hpp"
+#include "conf/common.hpp"
+
+namespace ndn {
+
+class ValidatorConfig : public Validator
+{
+public:
+ class Error : public Validator::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : Validator::Error(what)
+ {
+ }
+ };
+
+ static const shared_ptr<CertificateCache> DEFAULT_CERTIFICATE_CACHE;
+
+ ValidatorConfig(shared_ptr<Face> face,
+ shared_ptr<CertificateCache> certificateCache = DEFAULT_CERTIFICATE_CACHE,
+ const int stepLimit = 10);
+
+ virtual
+ ~ValidatorConfig()
+ {
+ }
+
+ void
+ load(const std::string& filename);
+
+ void
+ load(const std::string& input, const std::string& filename);
+
+ void
+ load(std::istream& input, const std::string& filename);
+
+protected:
+ virtual void
+ checkPolicy(const Data& data,
+ int stepCount,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps);
+
+ virtual void
+ checkPolicy(const Interest& interest,
+ int stepCount,
+ const OnInterestValidated& onValidated,
+ const OnInterestValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps);
+
+private:
+ template<class Packet, class OnValidated, class OnFailed>
+ void
+ checkSignature(const Packet& packet,
+ const Signature& signature,
+ int stepCount,
+ const OnValidated& onValidated,
+ const OnFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps);
+
+ template<class Packet, class OnValidated, class OnFailed>
+ void
+ onCertValidated(const shared_ptr<const Data>& signCertificate,
+ const shared_ptr<const Packet>& packet,
+ const OnValidated& onValidated,
+ const OnFailed& onValidationFailed);
+
+ template<class Packet, class OnFailed>
+ void
+ onCertFailed(const shared_ptr<const Data>& signCertificate,
+ const std::string& failureInfo,
+ const shared_ptr<const Packet>& packet,
+ const OnFailed& onValidationFailed);
+
+ void
+ process(const security::conf::ConfigSection& configSection,
+ const std::string& filename);
+
+ void
+ onConfigRule(const security::conf::ConfigSection& section,
+ const std::string& filename);
+
+ void
+ onConfigTrustAnchor(const security::conf::ConfigSection& section,
+ const std::string& filename);
+
+private:
+ typedef security::conf::Rule<Interest> InterestRule;
+ typedef security::conf::Rule<Data> DataRule;
+ typedef std::vector<shared_ptr<InterestRule> > InterestRuleList;
+ typedef std::vector<shared_ptr<DataRule> > DataRuleList;
+ typedef std::map<Name, shared_ptr<IdentityCertificate> > AnchorList;
+
+ int m_stepLimit;
+ shared_ptr<CertificateCache> m_certificateCache;
+
+ InterestRuleList m_interestRules;
+ DataRuleList m_dataRules;
+ AnchorList m_anchors;
+};
+
+template<class Packet, class OnValidated, class OnFailed>
+void
+ValidatorConfig::checkSignature(const Packet& packet,
+ const Signature& signature,
+ int stepCount,
+ const OnValidated& onValidated,
+ const OnFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps)
+{
+ if (signature.getType() == Signature::Sha256)
+ {
+ SignatureSha256 sigSha256(signature);
+
+ if (verifySignature(packet, sigSha256))
+ return onValidated(packet.shared_from_this());
+ else
+ return onValidationFailed(packet.shared_from_this(),
+ "Sha256 Signature cannot be verified!");
+ }
+
+ if (signature.getType() == Signature::Sha256WithRsa)
+ {
+ SignatureSha256WithRsa sigSha256Rsa(signature);
+ Name keyLocatorName = sigSha256Rsa.getKeyLocator().getName();
+
+ shared_ptr<const Certificate> trustedCert;
+
+ AnchorList::const_iterator it = m_anchors.find(keyLocatorName);
+ if (m_anchors.end() == it)
+ trustedCert = m_certificateCache->getCertificate(keyLocatorName);
+ else
+ trustedCert = it->second;
+
+ if (static_cast<bool>(trustedCert))
+ {
+ if (verifySignature(packet, sigSha256Rsa, trustedCert->getPublicKeyInfo()))
+ return onValidated(packet.shared_from_this());
+ else
+ return onValidationFailed(packet.shared_from_this(),
+ "Cannot verify signature");
+ }
+ else
+ {
+ OnDataValidated onCertValidated =
+ bind(&ValidatorConfig::onCertValidated<Packet, OnValidated, OnFailed>,
+ this, _1, packet.shared_from_this(), onValidated, onValidationFailed);
+
+ OnDataValidationFailed onCertValidationFailed =
+ bind(&ValidatorConfig::onCertFailed<Packet, OnFailed>,
+ this, _1, _2, packet.shared_from_this(), onValidationFailed);
+
+ Interest certInterest(keyLocatorName);
+
+ shared_ptr<ValidationRequest> nextStep =
+ make_shared<ValidationRequest>(boost::cref(certInterest),
+ onCertValidated,
+ onCertValidationFailed,
+ 1, stepCount + 1);
+
+ nextSteps.push_back(nextStep);
+ return;
+ }
+ }
+ return onValidationFailed(packet.shared_from_this(), "Unsupported Signature Type!");
+}
+
+template<class Packet, class OnValidated, class OnFailed>
+void
+ValidatorConfig::onCertValidated(const shared_ptr<const Data>& signCertificate,
+ const shared_ptr<const Packet>& packet,
+ const OnValidated& onValidated,
+ const OnFailed& onValidationFailed)
+{
+ shared_ptr<IdentityCertificate> certificate =
+ make_shared<IdentityCertificate>(boost::cref(*signCertificate));
+
+ if (!certificate->isTooLate() && !certificate->isTooEarly())
+ {
+ m_certificateCache->insertCertificate(certificate);
+
+ if (verifySignature(*packet, certificate->getPublicKeyInfo()))
+ return onValidated(packet);
+ else
+ return onValidationFailed(packet,
+ "Cannot verify signature: " +
+ packet->getName().toUri());
+ }
+ else
+ {
+ return onValidationFailed(packet,
+ "Signing certificate " +
+ signCertificate->getName().toUri() +
+ " is no longer valid.");
+ }
+}
+
+template<class Packet, class OnFailed>
+void
+ValidatorConfig::onCertFailed(const shared_ptr<const Data>& signCertificate,
+ const std::string& failureInfo,
+ const shared_ptr<const Packet>& packet,
+ const OnFailed& onValidationFailed)
+{
+ onValidationFailed(packet, failureInfo);
+}
+
+} // namespace ndn
+
+#endif // NDN_SECURITY_VALIDATOR_CONFIG_HPP
diff --git a/src/security/validator-regex.cpp b/src/security/validator-regex.cpp
index ec22de8..0f09741 100644
--- a/src/security/validator-regex.cpp
+++ b/src/security/validator-regex.cpp
@@ -19,127 +19,147 @@
namespace ndn {
-const shared_ptr<CertificateCache> ValidatorRegex::DefaultCertificateCache = shared_ptr<CertificateCache>();
+const shared_ptr<CertificateCache> ValidatorRegex::DEFAULT_CERTIFICATE_CACHE;
ValidatorRegex::ValidatorRegex(shared_ptr<Face> face,
- shared_ptr<CertificateCache> certificateCache /* = DefaultCertificateCache */,
- const int stepLimit /* = 3 */)
+ shared_ptr<CertificateCache> certificateCache,
+ const int stepLimit)
: Validator(face)
, m_stepLimit(stepLimit)
, m_certificateCache(certificateCache)
{
- if(!static_cast<bool>(face))
+ if (!static_cast<bool>(face))
throw Error("Face is not set!");
- if(!static_cast<bool>(m_certificateCache))
+ if (!static_cast<bool>(m_certificateCache))
m_certificateCache = make_shared<CertificateCacheTtl>(m_face->ioService());
}
void
-ValidatorRegex::onCertificateValidated(const shared_ptr<const Data> &signCertificate,
- const shared_ptr<const Data> &data,
- const OnDataValidated &onValidated,
- const OnDataValidationFailed &onValidationFailed)
+ValidatorRegex::onCertificateValidated(const shared_ptr<const Data>& signCertificate,
+ const shared_ptr<const Data>& data,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed)
{
- shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>(*signCertificate);
-
- if(!certificate->isTooLate() && !certificate->isTooEarly())
+ shared_ptr<IdentityCertificate> certificate =
+ make_shared<IdentityCertificate>(boost::cref(*signCertificate));
+
+ if (!certificate->isTooLate() && !certificate->isTooEarly())
{
m_certificateCache->insertCertificate(certificate);
-
- if(verifySignature(*data, certificate->getPublicKeyInfo()))
+
+ if (verifySignature(*data, certificate->getPublicKeyInfo()))
return onValidated(data);
else
- return onValidationFailed(data,
- "Cannot verify signature: " + data->getName().toUri());
+ return onValidationFailed(data,
+ "Cannot verify signature: " +
+ data->getName().toUri());
}
else
{
_LOG_DEBUG("Wrong validity:");
- return onValidationFailed(data,
- "Signing certificate " + signCertificate->getName().toUri() + " is no longer valid.");
+ return onValidationFailed(data,
+ "Signing certificate " +
+ signCertificate->getName().toUri() +
+ " is no longer valid.");
}
}
void
-ValidatorRegex::onCertificateValidationFailed(const shared_ptr<const Data> &signCertificate,
+ValidatorRegex::onCertificateValidationFailed(const shared_ptr<const Data>& signCertificate,
const string& failureInfo,
- const shared_ptr<const Data> &data,
- const OnDataValidationFailed &onValidationFailed)
-{ onValidationFailed(data, failureInfo); }
+ const shared_ptr<const Data>& data,
+ const OnDataValidationFailed& onValidationFailed)
+{
+ onValidationFailed(data, failureInfo);
+}
void
-ValidatorRegex::checkPolicy(const Data& data,
- int stepCount,
- const OnDataValidated &onValidated,
- const OnDataValidationFailed &onValidationFailed,
- vector<shared_ptr<ValidationRequest> > &nextSteps)
+ValidatorRegex::checkPolicy(const Data& data,
+ int stepCount,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed,
+ vector<shared_ptr<ValidationRequest> >& nextSteps)
{
- if(m_stepLimit == stepCount)
- return onValidationFailed(data.shared_from_this(),
- "Maximum steps of validation reached: " + data.getName().toUri());
+ if (m_stepLimit == stepCount)
+ return onValidationFailed(data.shared_from_this(),
+ "Maximum steps of validation reached: " +
+ data.getName().toUri());
- RuleList::iterator it = m_mustFailVerify.begin();
- for(; it != m_mustFailVerify.end(); it++)
- if((*it)->satisfy(data))
+ for (RuleList::iterator it = m_mustFailVerify.begin();
+ it != m_mustFailVerify.end();
+ it++)
+ if ((*it)->satisfy(data))
return onValidationFailed(data.shared_from_this(),
- "Comply with mustFail policy: " + data.getName().toUri());
+ "Comply with mustFail policy: " +
+ data.getName().toUri());
- it = m_verifyPolicies.begin();
- for(; it != m_verifyPolicies.end(); it++)
+ for (RuleList::iterator it = m_verifyPolicies.begin();
+ it != m_verifyPolicies.end();
+ it++)
{
- if((*it)->satisfy(data))
+ if ((*it)->satisfy(data))
{
try
{
- SignatureSha256WithRsa sig(data.getSignature());
-
+ SignatureSha256WithRsa sig(data.getSignature());
+
Name keyLocatorName = sig.getKeyLocator().getName();
shared_ptr<const Certificate> trustedCert;
- if(m_trustAnchors.end() == m_trustAnchors.find(keyLocatorName))
+ if (m_trustAnchors.end() == m_trustAnchors.find(keyLocatorName))
trustedCert = m_certificateCache->getCertificate(keyLocatorName);
else
trustedCert = m_trustAnchors[keyLocatorName];
-
- if(static_cast<bool>(trustedCert)){
- if(verifySignature(data, sig, trustedCert->getPublicKeyInfo()))
- return onValidated(data.shared_from_this());
- else
- return onValidationFailed(data.shared_from_this(),
- "Cannot verify signature: " + data.getName().toUri());
- }
- else{
- // _LOG_DEBUG("KeyLocator is not trust anchor");
- OnDataValidated onKeyValidated = bind(&ValidatorRegex::onCertificateValidated, this,
- _1, data.shared_from_this(), onValidated, onValidationFailed);
-
- OnDataValidationFailed onKeyValidationFailed = bind(&ValidatorRegex::onCertificateValidationFailed, this,
- _1, _2, data.shared_from_this(), onValidationFailed);
- shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>(Interest(boost::cref(sig.getKeyLocator().getName())),
- onKeyValidated,
- onKeyValidationFailed,
- 3,
- stepCount + 1);
- nextSteps.push_back(nextStep);
+ if (static_cast<bool>(trustedCert))
+ {
+ if (verifySignature(data, sig, trustedCert->getPublicKeyInfo()))
+ return onValidated(data.shared_from_this());
+ else
+ return onValidationFailed(data.shared_from_this(),
+ "Cannot verify signature: " +
+ data.getName().toUri());
+ }
+ else
+ {
+ // _LOG_DEBUG("KeyLocator is not trust anchor");
+ OnDataValidated onKeyValidated =
+ bind(&ValidatorRegex::onCertificateValidated, this, _1,
+ data.shared_from_this(), onValidated, onValidationFailed);
- return;
- }
+ OnDataValidationFailed onKeyValidationFailed =
+ bind(&ValidatorRegex::onCertificateValidationFailed, this, _1, _2,
+ data.shared_from_this(), onValidationFailed);
+
+ Interest interest(sig.getKeyLocator().getName());
+ shared_ptr<ValidationRequest> nextStep =
+ make_shared<ValidationRequest>(boost::cref(interest),
+ onKeyValidated,
+ onKeyValidationFailed,
+ 3,
+ stepCount + 1);
+
+ nextSteps.push_back(nextStep);
+
+ return;
+ }
}
- catch(SignatureSha256WithRsa::Error &e)
- {
- return onValidationFailed(data.shared_from_this(),
- "Not SignatureSha256WithRsa signature: " + data.getName().toUri());
- }
- catch(KeyLocator::Error &e)
+ catch (const SignatureSha256WithRsa::Error& e)
{
return onValidationFailed(data.shared_from_this(),
- "Key Locator is not a name: " + data.getName().toUri());
+ "Not SignatureSha256WithRsa signature: " +
+ data.getName().toUri());
+ }
+ catch (const KeyLocator::Error& e)
+ {
+ return onValidationFailed(data.shared_from_this(),
+ "Key Locator is not a name: " +
+ data.getName().toUri());
}
}
}
- return onValidationFailed(data.shared_from_this(),
+ return onValidationFailed(data.shared_from_this(),
"No policy found for data: " + data.getName().toUri());
}
diff --git a/src/security/validator-regex.hpp b/src/security/validator-regex.hpp
index 9caa380..1124620 100644
--- a/src/security/validator-regex.hpp
+++ b/src/security/validator-regex.hpp
@@ -19,61 +19,73 @@
class ValidatorRegex : public Validator
{
public:
- struct Error : public Validator::Error { Error(const std::string &what) : Validator::Error(what) {} };
+ class Error : public Validator::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : Validator::Error(what)
+ {
+ }
+ };
- static const shared_ptr<CertificateCache> DefaultCertificateCache;
-
+ static const shared_ptr<CertificateCache> DEFAULT_CERTIFICATE_CACHE;
+
ValidatorRegex(shared_ptr<Face> face,
- shared_ptr<CertificateCache> certificateCache = DefaultCertificateCache,
+ shared_ptr<CertificateCache> certificateCache = DEFAULT_CERTIFICATE_CACHE,
const int stepLimit = 3);
-
- virtual
- ~ValidatorRegex() {}
-
+
+ virtual
+ ~ValidatorRegex()
+ {
+ }
+
/**
* @brief Add a rule for data verification.
*
* @param policy The verification rule
*/
inline void
- addDataVerificationRule (shared_ptr<SecRuleRelative> rule);
-
+ addDataVerificationRule(shared_ptr<SecRuleRelative> rule);
+
/**
* @brief Add a trust anchor
*
- * @param certificate The trust anchor
+ * @param certificate The trust anchor
*/
- inline void
+ inline void
addTrustAnchor(shared_ptr<IdentityCertificate> certificate);
protected:
virtual void
- checkPolicy (const Data& data,
- int stepCount,
- const OnDataValidated &onValidated,
- const OnDataValidationFailed &onValidationFailed,
- std::vector<shared_ptr<ValidationRequest> > &nextSteps);
+ checkPolicy(const Data& data,
+ int stepCount,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps);
virtual void
- checkPolicy (const Interest& interest,
- int stepCount,
- const OnInterestValidated &onValidated,
- const OnInterestValidationFailed &onValidationFailed,
- std::vector<shared_ptr<ValidationRequest> > &nextSteps)
- { onValidationFailed(interest.shared_from_this(), "No policy for signed interest checking"); }
+ checkPolicy(const Interest& interest,
+ int stepCount,
+ const OnInterestValidated& onValidated,
+ const OnInterestValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps)
+ {
+ onValidationFailed(interest.shared_from_this(), "No policy for signed interest checking");
+ }
void
- onCertificateValidated(const shared_ptr<const Data> &signCertificate,
- const shared_ptr<const Data> &data,
- const OnDataValidated &onValidated,
- const OnDataValidationFailed &onValidationFailed);
-
+ onCertificateValidated(const shared_ptr<const Data>& signCertificate,
+ const shared_ptr<const Data>& data,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed);
+
void
- onCertificateValidationFailed(const shared_ptr<const Data> &signCertificate,
+ onCertificateValidationFailed(const shared_ptr<const Data>& signCertificate,
const std::string& failureInfo,
- const shared_ptr<const Data> &data,
- const OnDataValidationFailed &onValidationFailed);
-
+ const shared_ptr<const Data>& data,
+ const OnDataValidationFailed& onValidationFailed);
+
protected:
typedef std::vector< shared_ptr<SecRuleRelative> > RuleList;
typedef std::vector< shared_ptr<Regex> > RegexList;
@@ -85,13 +97,17 @@
std::map<Name, shared_ptr<IdentityCertificate> > m_trustAnchors;
};
-inline void
-ValidatorRegex::addDataVerificationRule (shared_ptr<SecRuleRelative> rule)
-{ rule->isPositive() ? m_verifyPolicies.push_back(rule) : m_mustFailVerify.push_back(rule); }
-
-inline void
+inline void
+ValidatorRegex::addDataVerificationRule(shared_ptr<SecRuleRelative> rule)
+{
+ rule->isPositive() ? m_verifyPolicies.push_back(rule) : m_mustFailVerify.push_back(rule);
+}
+
+inline void
ValidatorRegex::addTrustAnchor(shared_ptr<IdentityCertificate> certificate)
-{ m_trustAnchors[certificate->getName().getPrefix(-1)] = certificate; }
+{
+ m_trustAnchors[certificate->getName().getPrefix(-1)] = certificate;
+}
} // namespace ndn
diff --git a/src/security/validator.cpp b/src/security/validator.cpp
index f1d8035..cb5be23 100644
--- a/src/security/validator.cpp
+++ b/src/security/validator.cpp
@@ -21,47 +21,49 @@
namespace ndn {
-const shared_ptr<Face> Validator::DefaultFace = shared_ptr<Face>();
+const shared_ptr<Face> Validator::DEFAULT_FACE;
-Validator::Validator(shared_ptr<Face> face /* = DefaultFace */)
+Validator::Validator(shared_ptr<Face> face /* = DefaultFace */)
: m_face(face)
-{}
+{
+}
void
-Validator::validate(const Interest& interest,
- const OnInterestValidated &onValidated,
- const OnInterestValidationFailed &onValidationFailed,
+Validator::validate(const Interest& interest,
+ const OnInterestValidated& onValidated,
+ const OnInterestValidationFailed& onValidationFailed,
int stepCount)
{
vector<shared_ptr<ValidationRequest> > nextSteps;
checkPolicy(interest, stepCount, onValidated, onValidationFailed, nextSteps);
-
+
if (!nextSteps.empty())
{
- if(!static_cast<bool>(m_face))
- throw Error("Face should be set prior to verify method to call");
-
+ if (!static_cast<bool>(m_face))
+ throw Error("Face should be set before calling validate method");
+
vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this(), _1);
- for(; it != nextSteps.end(); it++)
+ for (; it != nextSteps.end(); it++)
m_face->expressInterest((*it)->m_interest,
- bind(&Validator::onData, this, _1, _2, *it),
- bind(&Validator::onTimeout,
- this, _1, (*it)->m_retry,
- onFailure,
+ bind(&Validator::onData, this, _1, _2, *it),
+ bind(&Validator::onTimeout,
+ this, _1, (*it)->m_retry,
+ onFailure,
*it));
}
else
{
- //If there is no nextStep, that means InterestPolicy has already been able to verify the Interest.
- //No more further processes.
+ // If there is no nextStep,
+ // that means InterestPolicy has already been able to verify the Interest.
+ // No more further processes.
}
}
void
-Validator::validate(const Data& data,
- const OnDataValidated &onValidated,
- const OnDataValidationFailed &onValidationFailed,
+Validator::validate(const Data& data,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed,
int stepCount)
{
vector<shared_ptr<ValidationRequest> > nextSteps;
@@ -69,44 +71,45 @@
if (!nextSteps.empty())
{
- if(!static_cast<bool>(m_face))
+ if (!static_cast<bool>(m_face))
throw Error("Face should be set prior to verify method to call");
vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
OnFailure onFailure = bind(onValidationFailed, data.shared_from_this(), _1);
- for(; it != nextSteps.end(); it++)
+ for (; it != nextSteps.end(); it++)
m_face->expressInterest((*it)->m_interest,
- bind(&Validator::onData, this, _1, _2, *it),
- bind(&Validator::onTimeout,
- this, _1, (*it)->m_retry,
+ bind(&Validator::onData, this, _1, _2, *it),
+ bind(&Validator::onTimeout,
+ this, _1, (*it)->m_retry,
onFailure,
*it));
}
else
{
- //If there is no nextStep, that means InterestPolicy has already been able to verify the Interest.
- //No more further processes.
+ // If there is no nextStep,
+ // that means Data Policy has already been able to verify the Interest.
+ // No more further processes.
}
}
void
-Validator::onData(const Interest& interest,
- Data& data,
+Validator::onData(const Interest& interest,
+ const Data& data,
const shared_ptr<ValidationRequest>& nextStep)
{
validate(data, nextStep->m_onValidated, nextStep->m_onDataValidated, nextStep->m_stepCount);
}
void
-Validator::onTimeout(const Interest& interest,
- int retry,
- const OnFailure &onFailure,
+Validator::onTimeout(const Interest& interest,
+ int retry,
+ const OnFailure& onFailure,
const shared_ptr<ValidationRequest>& nextStep)
{
if (retry > 0)
// Issue the same expressInterest except decrement retry.
- m_face->expressInterest(interest,
- bind(&Validator::onData, this, _1, _2, nextStep),
+ m_face->expressInterest(interest,
+ bind(&Validator::onData, this, _1, _2, nextStep),
bind(&Validator::onTimeout, this, _1, retry - 1, onFailure, nextStep));
else
onFailure("Cannot fetch cert: " + interest.getName().toUri());
@@ -117,20 +120,21 @@
{
try
{
- switch(data.getSignature().getType()){
- case Signature::Sha256WithRsa:
+ switch (data.getSignature().getType())
{
- SignatureSha256WithRsa sigSha256Rsa(data.getSignature());
- return verifySignature(data, sigSha256Rsa, key);
+ case Signature::Sha256WithRsa:
+ {
+ SignatureSha256WithRsa sigSha256Rsa(data.getSignature());
+ return verifySignature(data, sigSha256Rsa, key);
+ }
+ default:
+ {
+ _LOG_DEBUG("verifySignature: Unknown signature type: " << data.getSignature().getType());
+ return false;
+ }
}
- default:
- {
- _LOG_DEBUG("verifySignature: Unknown signature type: " << data.getSignature().getType());
- return false;
- }
- }
}
- catch(Signature::Error &e)
+ catch (const Signature::Error& e)
{
_LOG_DEBUG("verifySignature: " << e.what());
return false;
@@ -141,40 +145,41 @@
bool
Validator::verifySignature(const Interest& interest, const PublicKey& key)
{
- const Name &interestName = interest.getName();
+ const Name& interestName = interest.getName();
- if(interestName.size() < 2)
+ if (interestName.size() < 2)
return false;
try
{
const Block& nameBlock = interestName.wireEncode();
- Signature sig(interestName[-2].blockFromValue(),
+ Signature sig(interestName[-2].blockFromValue(),
interestName[-1].blockFromValue());
- switch(sig.getType()){
- case Signature::Sha256WithRsa:
+ switch (sig.getType())
{
- SignatureSha256WithRsa sigSha256Rsa(sig);
+ case Signature::Sha256WithRsa:
+ {
+ SignatureSha256WithRsa sigSha256Rsa(sig);
- return verifySignature(nameBlock.value(),
- nameBlock.value_size() - interestName[-1].size(),
- sigSha256Rsa, key);
+ return verifySignature(nameBlock.value(),
+ nameBlock.value_size() - interestName[-1].size(),
+ sigSha256Rsa, key);
+ }
+ default:
+ {
+ _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
+ return false;
+ }
}
- default:
- {
- _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
- return false;
- }
- }
}
- catch(Signature::Error &e)
+ catch (const Signature::Error& e)
{
_LOG_DEBUG("verifySignature: " << e.what());
return false;
}
- catch(Block::Error &e)
+ catch (const Block::Error& e)
{
_LOG_DEBUG("verifySignature: " << e.what());
return false;
@@ -187,20 +192,21 @@
{
try
{
- switch(sig.getType()){
- case Signature::Sha256WithRsa:
+ switch (sig.getType())
{
- SignatureSha256WithRsa sigSha256Rsa(sig);
- return verifySignature(data, sigSha256Rsa, key);
+ case Signature::Sha256WithRsa:
+ {
+ SignatureSha256WithRsa sigSha256Rsa(sig);
+ return verifySignature(data, sigSha256Rsa, key);
+ }
+ default:
+ {
+ _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
+ return false;
+ }
}
- default:
- {
- _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
- return false;
- }
- }
}
- catch(Signature::Error &e)
+ catch (const Signature::Error& e)
{
_LOG_DEBUG("verifySignature: " << e.what());
return false;
@@ -209,7 +215,10 @@
}
bool
-Validator::verifySignature(const uint8_t* buf, const size_t size, const SignatureSha256WithRsa& sig, const PublicKey& key)
+Validator::verifySignature(const uint8_t* buf,
+ const size_t size,
+ const SignatureSha256WithRsa& sig,
+ const PublicKey& key)
{
try
{
@@ -221,10 +230,12 @@
queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
publicKey.Load(queue);
- RSASS<PKCS1v15, SHA256>::Verifier verifier (publicKey);
- return verifier.VerifyMessage(buf, size, sig.getValue().value(), sig.getValue().value_size());
+ RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey);
+ return verifier.VerifyMessage(buf, size,
+ sig.getValue().value(),
+ sig.getValue().value_size());
}
- catch(CryptoPP::Exception& e)
+ catch (const CryptoPP::Exception& e)
{
_LOG_DEBUG("verifySignature: " << e.what());
return false;
@@ -239,23 +250,20 @@
ConstBufferPtr buffer = crypto::sha256(buf, size);
const Block& sigValue = sig.getValue();
- if(static_cast<bool>(buffer)
- && buffer->size() == sigValue.value_size()
- && buffer->size() == crypto::SHA256_DIGEST_SIZE)
+ if (static_cast<bool>(buffer) &&
+ buffer->size() == sigValue.value_size() &&
+ buffer->size() == crypto::SHA256_DIGEST_SIZE)
{
const uint8_t* p1 = buffer->buf();
const uint8_t* p2 = sigValue.value();
- for(size_t i = 0; i < crypto::SHA256_DIGEST_SIZE; i++)
- if(p1[i] != p2[i])
- return false;
- return true;
+ return 0 == memcmp(p1, p2, crypto::SHA256_DIGEST_SIZE);
}
else
return false;
}
- catch(CryptoPP::Exception& e)
+ catch (const CryptoPP::Exception& e)
{
_LOG_DEBUG("verifySignature: " << e.what());
return false;
diff --git a/src/security/validator.hpp b/src/security/validator.hpp
index 5147dd7..2b55782 100644
--- a/src/security/validator.hpp
+++ b/src/security/validator.hpp
@@ -20,39 +20,56 @@
namespace ndn {
/**
- * Validator is one of the main classes of the security library.
+ * @brief Validator is one of the main classes of the security library.
*
* The Validator class provides the interfaces for packet validation.
*/
class Validator {
public:
- struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
- static const shared_ptr<Face> DefaultFace;
+ static const shared_ptr<Face> DEFAULT_FACE;
- Validator (shared_ptr<Face> face = DefaultFace);
+ explicit
+ Validator(shared_ptr<Face> face = DEFAULT_FACE);
/**
- * @brief Validate Data and call either onValidated or onValidationFailed.
- *
+ * @brief Validate Data and call either onValidated or onValidationFailed.
+ *
* @param data The Data with the signature to check.
* @param onValidated If the Data is validated, this calls onValidated(data).
* @param onValidationFailed If the Data validation fails, this calls onValidationFailed(data).
*/
void
- validate (const Data& data, const OnDataValidated &onValidated, const OnDataValidationFailed &onValidationFailed)
- { validate (data, onValidated, onValidationFailed, 0); }
+ validate(const Data& data,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed)
+ {
+ validate(data, onValidated, onValidationFailed, 0);
+ }
/**
- * @brief Validate Interest and call either onValidated or onValidationFailed.
- *
+ * @brief Validate Interest and call either onValidated or onValidationFailed.
+ *
* @param interest The Interest with the signature to check.
* @param onValidated If the Interest is validated, this calls onValidated(interest).
* @param onValidationFailed If the Interest validation fails, this calls onValidationFailed(interest).
*/
void
- validate (const Interest& interest, const OnInterestValidated &onValidated, const OnInterestValidationFailed &onValidationFailed)
- { validate (interest, onValidated, onValidationFailed, 0); }
+ validate(const Interest& interest,
+ const OnInterestValidated& onValidated,
+ const OnInterestValidationFailed& onValidationFailed)
+ {
+ validate(interest, onValidated, onValidationFailed, 0);
+ }
/*****************************************
* verifySignature method set *
@@ -60,53 +77,109 @@
/// @brief Verify the data using the publicKey.
static bool
- verifySignature (const Data& data, const PublicKey& publicKey);
+ verifySignature(const Data& data, const PublicKey& publicKey);
- /// @brief Verify the signed Interest using the publicKey.
+ /**
+ * @brief Verify the signed Interest using the publicKey.
+ *
+ * (Note the signature covers the first n-2 name components).
+ */
static bool
- verifySignature (const Interest& interest, const PublicKey& publicKey);
+ verifySignature(const Interest& interest, const PublicKey& publicKey);
/// @brief Verify the blob using the publicKey against the signature.
static bool
- verifySignature (const Buffer& blob, const Signature& sig, const PublicKey& publicKey);
+ verifySignature(const Buffer& blob, const Signature& sig, const PublicKey& publicKey);
/// @brief Verify the data using the publicKey against the SHA256-RSA signature.
static bool
- verifySignature (const Data& data, const SignatureSha256WithRsa& sig, const PublicKey& publicKey)
- { return verifySignature (data.wireEncode().value(),
- data.wireEncode().value_size() - data.getSignature().getValue().size(),
- sig, publicKey); }
+ verifySignature(const Data& data,
+ const SignatureSha256WithRsa& sig,
+ const PublicKey& publicKey)
+ {
+ return verifySignature(data.wireEncode().value(),
+ data.wireEncode().value_size() - data.getSignature().getValue().size(),
+ sig, publicKey);
+ }
+
+ /** @brief Verify the interest using the publicKey against the SHA256-RSA signature.
+ *
+ * (Note the signature covers the first n-2 name components).
+ */
+ static bool
+ verifySignature(const Interest& interest,
+ const SignatureSha256WithRsa& sig,
+ const PublicKey& publicKey)
+ {
+ if (interest.getName().size() < 2)
+ return false;
+
+ Name signedName = interest.getName().getPrefix(-2);
+
+ return verifySignature(signedName.wireEncode().value(),
+ signedName.wireEncode().value_size(),
+ sig, publicKey);
+ }
/// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
static bool
- verifySignature (const Buffer& blob, const SignatureSha256WithRsa& sig, const PublicKey& publicKey)
- { return verifySignature (blob.buf(), blob.size(), sig, publicKey); }
-
+ verifySignature(const Buffer& blob,
+ const SignatureSha256WithRsa& sig,
+ const PublicKey& publicKey)
+ {
+ return verifySignature(blob.buf(), blob.size(), sig, publicKey);
+ }
+
/// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
static bool
- verifySignature (const uint8_t* buf, const size_t size, const SignatureSha256WithRsa &sig, const PublicKey &publicKey);
+ verifySignature(const uint8_t* buf,
+ const size_t size,
+ const SignatureSha256WithRsa& sig,
+ const PublicKey& publicKey);
/// @brief Verify the data against the SHA256 signature.
static bool
- verifySignature (const Data& data, const SignatureSha256& sig)
- { return verifySignature (data.wireEncode().value(),
- data.wireEncode().value_size() - data.getSignature().getValue().size(),
- sig); }
+ verifySignature(const Data& data, const SignatureSha256& sig)
+ {
+ return verifySignature(data.wireEncode().value(),
+ data.wireEncode().value_size() -
+ data.getSignature().getValue().size(),
+ sig);
+ }
+
+ /** @brief Verify the interest against the SHA256 signature.
+ *
+ * (Note the signature covers the first n-2 name components).
+ */
+ static bool
+ verifySignature(const Interest& interest, const SignatureSha256& sig)
+ {
+ if (interest.getName().size() < 2)
+ return false;
+
+ Name signedName = interest.getName().getPrefix(-2);
+
+ return verifySignature(signedName.wireEncode().value(),
+ signedName.wireEncode().value_size(),
+ sig);
+ }
/// @brief Verify the blob against the SHA256 signature.
static bool
- verifySignature (const Buffer& blob, const SignatureSha256& sig)
- { return verifySignature (blob.buf(), blob.size(), sig); }
-
+ verifySignature(const Buffer& blob, const SignatureSha256& sig)
+ {
+ return verifySignature (blob.buf(), blob.size(), sig);
+ }
+
/// @brief Verify the blob against the SHA256 signature.
static bool
- verifySignature (const uint8_t* buf, const size_t size, const SignatureSha256& sig);
+ verifySignature(const uint8_t* buf, const size_t size, const SignatureSha256& sig);
protected:
/**
- * @brief Check the Data against validation policy and return the next validation step if necessary.
+ * @brief Check the Data against policy and return the next validation step if necessary.
*
* If there is no next validation step, that validation MUST have been done.
* i.e., either onValidated or onValidationFailed callback is invoked.
@@ -118,11 +191,11 @@
* @param nextSteps On return, contains the next validation step.
*/
virtual void
- checkPolicy (const Data& data,
- int stepCount,
- const OnDataValidated &onValidated,
- const OnDataValidationFailed &onValidationFailed,
- std::vector<shared_ptr<ValidationRequest> > &nextSteps) = 0;
+ checkPolicy(const Data& data,
+ int stepCount,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
/**
* @brief Check the Interest against validation policy and return the next validation step if necessary.
@@ -137,39 +210,39 @@
* @return the indication of next validation step, null if there is no further step.
*/
virtual void
- checkPolicy (const Interest& interest,
- int stepCount,
- const OnInterestValidated &onValidated,
- const OnInterestValidationFailed &onValidationFailed,
- std::vector<shared_ptr<ValidationRequest> > &nextSteps) = 0;
+ checkPolicy(const Interest& interest,
+ int stepCount,
+ const OnInterestValidated& onValidated,
+ const OnInterestValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
private:
typedef function< void (const std::string&) > OnFailure;
-
+
/// @brief Process the received certificate.
void
- onData (const Interest& interest,
- Data& data,
- const shared_ptr<ValidationRequest>& nextStep);
-
+ onData(const Interest& interest,
+ const Data& data,
+ const shared_ptr<ValidationRequest>& nextStep);
+
/// @brief Re-express the interest if it times out.
void
- onTimeout (const Interest& interest,
- int retry,
- const OnFailure &onFailure,
- const shared_ptr<ValidationRequest>& nextStep);
+ onTimeout(const Interest& interest,
+ int retry,
+ const OnFailure& onFailure,
+ const shared_ptr<ValidationRequest>& nextStep);
void
- validate (const Data& data,
- const OnDataValidated &onValidated,
- const OnDataValidationFailed &onValidationFailed,
- int stepCount);
+ validate(const Data& data,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed,
+ int stepCount);
void
- validate (const Interest& interest,
- const OnInterestValidated &onValidated,
- const OnInterestValidationFailed &onValidationFailed,
- int stepCount);
+ validate(const Interest& interest,
+ const OnInterestValidated& onValidated,
+ const OnInterestValidationFailed& onValidationFailed,
+ int stepCount);
protected:
shared_ptr<Face> m_face;
diff --git a/src/util/command-interest-validator.hpp b/src/util/command-interest-validator.hpp
index 257f476..ca65f27 100644
--- a/src/util/command-interest-validator.hpp
+++ b/src/util/command-interest-validator.hpp
@@ -4,8 +4,8 @@
* See COPYING for copyright and distribution information.
*/
-#ifndef NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP
-#define NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP
+#ifndef NDN_UTIL_COMMAND_INTEREST_VALIDATOR_HPP
+#define NDN_UTIL_COMMAND_INTEREST_VALIDATOR_HPP
#include "../security/validator.hpp"
#include "../security/identity-certificate.hpp"
@@ -25,7 +25,8 @@
GRACE_INTERVAL = 3000 // ms
};
- CommandInterestValidator(const time::milliseconds& graceInterval = time::milliseconds(static_cast<int>(GRACE_INTERVAL)))
+ CommandInterestValidator(const time::milliseconds& graceInterval =
+ time::milliseconds(static_cast<int>(GRACE_INTERVAL)))
: m_graceInterval(graceInterval < time::milliseconds::zero() ?
time::milliseconds(static_cast<int>(GRACE_INTERVAL)) : graceInterval)
{
@@ -44,21 +45,21 @@
protected:
virtual void
- checkPolicy (const Data& data,
- int stepCount,
- const OnDataValidated &onValidated,
- const OnDataValidationFailed &onValidationFailed,
- std::vector<shared_ptr<ValidationRequest> > &nextSteps)
+ checkPolicy(const Data& data,
+ int stepCount,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps)
{
onValidationFailed(data.shared_from_this(), "No policy for data checking");
}
virtual void
- checkPolicy (const Interest& interest,
- int stepCount,
- const OnInterestValidated &onValidated,
- const OnInterestValidationFailed &onValidationFailed,
- std::vector<shared_ptr<ValidationRequest> > &nextSteps);
+ checkPolicy(const Interest& interest,
+ int stepCount,
+ const OnInterestValidated& onValidated,
+ const OnInterestValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps);
private:
time::milliseconds m_graceInterval; //ms
std::map<Name, PublicKey> m_trustAnchorsForInterest;
@@ -69,14 +70,17 @@
};
inline void
-CommandInterestValidator::addInterestRule(const std::string& regex, const IdentityCertificate& certificate)
+CommandInterestValidator::addInterestRule(const std::string& regex,
+ const IdentityCertificate& certificate)
{
Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificate.getName());
addInterestRule(regex, keyName, certificate.getPublicKeyInfo());
}
inline void
-CommandInterestValidator::addInterestRule(const std::string& regex, const Name& keyName, const PublicKey& publicKey)
+CommandInterestValidator::addInterestRule(const std::string& regex,
+ const Name& keyName,
+ const PublicKey& publicKey)
{
m_trustAnchorsForInterest[keyName] = publicKey;
shared_ptr<Regex> interestRegex = make_shared<Regex>(regex);
@@ -85,11 +89,11 @@
}
inline void
-CommandInterestValidator::checkPolicy (const Interest& interest,
- int stepCount,
- const OnInterestValidated &onValidated,
- const OnInterestValidationFailed &onValidationFailed,
- std::vector<shared_ptr<ValidationRequest> > &nextSteps)
+CommandInterestValidator::checkPolicy(const Interest& interest,
+ int stepCount,
+ const OnInterestValidated& onValidated,
+ const OnInterestValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> >& nextSteps)
{
const Name& interestName = interest.getName();
@@ -106,24 +110,26 @@
Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
//Check if command is in the trusted scope
- bool inScope = false;
- for(std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
+ bool isInScope = false;
+ for (std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
scopeIt != m_trustScopeForInterest.end();
++scopeIt)
{
- if(scopeIt->satisfy(interestName, keyName))
+ if (scopeIt->satisfy(interestName, keyName))
{
- inScope = true;
+ isInScope = true;
break;
}
}
- if(inScope == false)
+
+ if (isInScope == false)
return onValidationFailed(interest.shared_from_this(),
"Signer cannot be authorized for the command: " + keyName.toUri());
//Check if timestamp is valid
- time::system_clock::TimePoint interestTime = time::fromUnixTimestamp(
- time::milliseconds(interestName.get(POS_TIMESTAMP).toNumber()));
+ time::system_clock::TimePoint interestTime =
+ time::fromUnixTimestamp(time::milliseconds(interestName.get(POS_TIMESTAMP).toNumber()));
+
time::system_clock::TimePoint currentTime = time::system_clock::now();
LastTimestampMap::iterator timestampIt = m_lastTimestamp.find(keyName);
@@ -133,7 +139,8 @@
interestTime <= currentTime + m_graceInterval))
{
return onValidationFailed(interest.shared_from_this(),
- "The command is not in grace interval: " + interest.getName().toUri());
+ "The command is not in grace interval: " +
+ interest.getName().toUri());
}
}
else
@@ -144,9 +151,10 @@
}
//Check signature
- if(!Validator::verifySignature(interestName.wireEncode().value(),
- interestName.wireEncode().value_size() - interestName[-1].size(),
- sig, m_trustAnchorsForInterest[keyName]))
+ if (!Validator::verifySignature(interestName.wireEncode().value(),
+ interestName.wireEncode().value_size() -
+ interestName[-1].size(),
+ sig, m_trustAnchorsForInterest[keyName]))
return onValidationFailed(interest.shared_from_this(),
"Signature cannot be validated: " + interest.getName().toUri());
@@ -165,4 +173,4 @@
} // namespace ndn
-#endif // NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP
+#endif // NDN_UTIL_COMMAND_INTEREST_VALIDATOR_HPP
diff --git a/src/util/regex/regex-top-matcher.hpp b/src/util/regex/regex-top-matcher.hpp
index 4d9c01e..f5b30c1 100644
--- a/src/util/regex/regex-top-matcher.hpp
+++ b/src/util/regex/regex-top-matcher.hpp
@@ -20,25 +20,25 @@
class RegexTopMatcher: public RegexMatcher
{
public:
- RegexTopMatcher(const std::string & expr, const std::string& expand = "");
-
+ RegexTopMatcher(const std::string& expr, const std::string& expand = "");
+
virtual
~RegexTopMatcher();
- bool
+ bool
match(const Name& name);
virtual bool
- match (const Name& name, const int& offset, const int& len);
+ match(const Name& name, const int& offset, const int& length);
- virtual Name
- expand (const std::string& expand = "");
+ virtual Name
+ expand(const std::string& expand = "");
static shared_ptr<RegexTopMatcher>
fromName(const Name& name, bool hasAnchor=false);
protected:
- virtual void
+ virtual void
compile();
private:
diff --git a/tests-integrated/security/test-validator-config.cpp b/tests-integrated/security/test-validator-config.cpp
new file mode 100644
index 0000000..0e778db
--- /dev/null
+++ b/tests-integrated/security/test-validator-config.cpp
@@ -0,0 +1,848 @@
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi0@cs.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "security/validator-config.hpp"
+
+#include <boost/test/unit_test.hpp>
+
+#include "security/key-chain.hpp"
+#include "util/io.hpp"
+
+
+using namespace std;
+
+namespace ndn {
+
+BOOST_AUTO_TEST_SUITE(TestValidatorConfig)
+
+void
+onValidated(const shared_ptr<const Data>& data)
+{
+ BOOST_CHECK(true);
+}
+
+void
+onValidationFailed(const shared_ptr<const Data>& data, const string& failureInfo)
+{
+ std::cerr << "Failure Info: " << failureInfo << std::endl;
+ BOOST_CHECK(false);
+}
+
+void
+onIntentionalFailureValidated(const shared_ptr<const Data>& data)
+{
+ BOOST_CHECK(false);
+}
+
+void
+onIntentionalFailureInvalidated(const shared_ptr<const Data>& data, const string& failureInfo)
+{
+ BOOST_CHECK(true);
+}
+
+void
+onValidated2(const shared_ptr<const Interest>& interest)
+{
+ BOOST_CHECK(true);
+}
+
+void
+onValidationFailed2(const shared_ptr<const Interest>& interest, const string& failureInfo)
+{
+ std::cerr << "Interest Name: " << interest->getName() << std::endl;
+ std::cerr << "Failure Info: " << failureInfo << std::endl;
+ BOOST_CHECK(false);
+}
+
+void
+onIntentionalFailureValidated2(const shared_ptr<const Interest>& interest)
+{
+ BOOST_CHECK(false);
+}
+
+void
+onIntentionalFailureInvalidated2(const shared_ptr<const Interest>& interest,
+ const string& failureInfo)
+{
+ BOOST_CHECK(true);
+}
+
+BOOST_AUTO_TEST_CASE(NameFilter)
+{
+ KeyChain keyChain;
+
+ Name identity("/TestValidatorConfig/NameFilter");
+ identity.appendVersion();
+ BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+ Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
+ shared_ptr<IdentityCertificate> idCert = keyChain.getCertificate(certName);
+ io::save(*idCert, "trust-anchor-1.cert");
+
+ Name dataName1("/simple/equal");
+ shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity));
+
+ Name dataName2("/simple/different");
+ shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity));
+
+ std::string CONFIG_1 =
+ "rule\n"
+ "{\n"
+ " id \"Simple Rule\"\n"
+ " for data\n"
+ " filter"
+ " {\n"
+ " type name\n"
+ " name /simple/equal\n"
+ " relation equal\n"
+ " }\n"
+ " checker\n"
+ " {\n"
+ " type customized\n"
+ " sig-type rsa-sha256\n"
+ " key-locator\n"
+ " {\n"
+ " type name\n"
+ " name ";
+
+ std::string CONFIG_2 =
+ "\n"
+ " relation equal\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "trust-anchor\n"
+ "{\n"
+ " type file\n"
+ " file-name \"trust-anchor-1.cert\"\n"
+ "}\n";
+ const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
+
+ const boost::filesystem::path CONFIG_PATH =
+ (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+ shared_ptr<Face> face = make_shared<Face>();
+ ValidatorConfig validator(face);
+ validator.load(CONFIG, CONFIG_PATH.native());
+
+ validator.validate(*data1,
+ bind(&onValidated, _1),
+ bind(&onValidationFailed, _1, _2));
+
+ validator.validate(*data2,
+ bind(&onIntentionalFailureValidated, _1),
+ bind(&onIntentionalFailureInvalidated, _1, _2));
+
+ keyChain.deleteIdentity(identity);
+
+ const boost::filesystem::path CERT_PATH =
+ (boost::filesystem::current_path() / std::string("trust-anchor-1.cert"));
+ boost::filesystem::remove(CERT_PATH);
+}
+
+BOOST_AUTO_TEST_CASE(NameFilter2)
+{
+ KeyChain keyChain;
+
+ Name identity("/TestValidatorConfig/NameFilter2");
+ identity.appendVersion();
+ BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+ Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
+ shared_ptr<IdentityCertificate> idCert = keyChain.getCertificate(certName);
+ io::save(*idCert, "trust-anchor-2.cert");
+
+ Name dataName1("/simple/isPrefixOf");
+ shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity));
+
+ Name dataName2("/simple/notPrefixOf");
+ shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity));
+
+ Name dataName3("/simple/isPrefixOf/anotherLevel");
+ shared_ptr<Data> data3 = make_shared<Data>(dataName3);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data3, identity));
+
+ std::string CONFIG_1 =
+ "rule\n"
+ "{\n"
+ " id \"Simple2 Rule\"\n"
+ " for data\n"
+ " filter"
+ " {\n"
+ " type name\n"
+ " name /simple/isPrefixOf\n"
+ " relation is-prefix-of\n"
+ " }\n"
+ " checker\n"
+ " {\n"
+ " type customized\n"
+ " sig-type rsa-sha256\n"
+ " key-locator\n"
+ " {\n"
+ " type name\n"
+ " name ";
+
+ std::string CONFIG_2 =
+ "\n"
+ " relation equal\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "trust-anchor\n"
+ "{\n"
+ " type file\n"
+ " file-name \"trust-anchor-2.cert\"\n"
+ "}\n";
+ const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
+
+ const boost::filesystem::path CONFIG_PATH =
+ (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+ shared_ptr<Face> face = make_shared<Face>();
+ ValidatorConfig validator(face);
+ validator.load(CONFIG, CONFIG_PATH.native());
+
+ validator.validate(*data1,
+ bind(&onValidated, _1),
+ bind(&onValidationFailed, _1, _2));
+
+ validator.validate(*data2,
+ bind(&onIntentionalFailureValidated, _1),
+ bind(&onIntentionalFailureInvalidated, _1, _2));
+
+ validator.validate(*data3,
+ bind(&onValidated, _1),
+ bind(&onValidationFailed, _1, _2));
+
+ keyChain.deleteIdentity(identity);
+
+ const boost::filesystem::path CERT_PATH =
+ (boost::filesystem::current_path() / std::string("trust-anchor-2.cert"));
+ boost::filesystem::remove(CERT_PATH);
+}
+
+BOOST_AUTO_TEST_CASE(NameFilter3)
+{
+ KeyChain keyChain;
+
+ Name identity("/TestValidatorConfig/NameFilter3");
+ identity.appendVersion();
+ BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+ Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
+ shared_ptr<IdentityCertificate> idCert = keyChain.getCertificate(certName);
+ io::save(*idCert, "trust-anchor-3.cert");
+
+ Name dataName1("/simple/isStrictPrefixOf");
+ shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity));
+
+ Name dataName2("/simple");
+ shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity));
+
+ Name dataName3("/simple/isStrictPrefixOf/anotherLevel");
+ shared_ptr<Data> data3 = make_shared<Data>(dataName3);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data3, identity));
+
+ std::string CONFIG_1 =
+ "rule\n"
+ "{\n"
+ " id \"Simple3 Rule\"\n"
+ " for data\n"
+ " filter"
+ " {\n"
+ " type name\n"
+ " name /simple/isStrictPrefixOf\n"
+ " relation is-strict-prefix-of\n"
+ " }\n"
+ " checker\n"
+ " {\n"
+ " type customized\n"
+ " sig-type rsa-sha256\n"
+ " key-locator\n"
+ " {\n"
+ " type name\n"
+ " name ";
+
+ std::string CONFIG_2 =
+ "\n"
+ " relation equal\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "trust-anchor\n"
+ "{\n"
+ " type file\n"
+ " file-name \"trust-anchor-3.cert\"\n"
+ "}\n";
+ const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
+
+ const boost::filesystem::path CONFIG_PATH =
+ (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+ shared_ptr<Face> face = make_shared<Face>();
+ ValidatorConfig validator(face);
+ validator.load(CONFIG, CONFIG_PATH.native());
+
+ validator.validate(*data1,
+ bind(&onIntentionalFailureValidated, _1),
+ bind(&onIntentionalFailureInvalidated, _1, _2));
+
+ validator.validate(*data2,
+ bind(&onIntentionalFailureValidated, _1),
+ bind(&onIntentionalFailureInvalidated, _1, _2));
+
+ validator.validate(*data3,
+ bind(&onValidated, _1),
+ bind(&onValidationFailed, _1, _2));
+
+ keyChain.deleteIdentity(identity);
+
+ const boost::filesystem::path CERT_PATH =
+ (boost::filesystem::current_path() / std::string("trust-anchor-3.cert"));
+ boost::filesystem::remove(CERT_PATH);
+}
+
+BOOST_AUTO_TEST_CASE(NameFilter4)
+{
+ KeyChain keyChain;
+
+ Name identity("/TestValidatorConfig/NameFilter4");
+ identity.appendVersion();
+ BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+ Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
+ shared_ptr<IdentityCertificate> idCert = keyChain.getCertificate(certName);
+ io::save(*idCert, "trust-anchor-4.cert");
+
+ Name dataName1("/simple/regex");
+ shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity));
+
+ Name dataName2("/simple/regex-wrong");
+ shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity));
+
+ Name dataName3("/simple/regex/correct");
+ shared_ptr<Data> data3 = make_shared<Data>(dataName3);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data3, identity));
+
+ std::string CONFIG_1 =
+ "rule\n"
+ "{\n"
+ " id \"Simple3 Rule\"\n"
+ " for data\n"
+ " filter"
+ " {\n"
+ " type name\n"
+ " regex ^<simple><regex>\n"
+ " }\n"
+ " checker\n"
+ " {\n"
+ " type customized\n"
+ " sig-type rsa-sha256\n"
+ " key-locator\n"
+ " {\n"
+ " type name\n"
+ " name ";
+
+ std::string CONFIG_2 =
+ "\n"
+ " relation equal\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "trust-anchor\n"
+ "{\n"
+ " type file\n"
+ " file-name \"trust-anchor-4.cert\"\n"
+ "}\n";
+ const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
+
+ const boost::filesystem::path CONFIG_PATH =
+ (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+ shared_ptr<Face> face = make_shared<Face>();
+ ValidatorConfig validator(face);
+ validator.load(CONFIG, CONFIG_PATH.native());
+
+ validator.validate(*data1,
+ bind(&onValidated, _1),
+ bind(&onValidationFailed, _1, _2));
+
+ validator.validate(*data2,
+ bind(&onIntentionalFailureValidated, _1),
+ bind(&onIntentionalFailureInvalidated, _1, _2));
+
+ validator.validate(*data3,
+ bind(&onValidated, _1),
+ bind(&onValidationFailed, _1, _2));
+
+ keyChain.deleteIdentity(identity);
+
+ const boost::filesystem::path CERT_PATH =
+ (boost::filesystem::current_path() / std::string("trust-anchor-4.cert"));
+ boost::filesystem::remove(CERT_PATH);
+}
+
+BOOST_AUTO_TEST_CASE(KeyLocatorNameChecker1)
+{
+ KeyChain keyChain;
+
+ Name identity("/TestValidatorConfig/KeyLocatorNameChecker1");
+ identity.appendVersion();
+ BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+ Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
+ shared_ptr<IdentityCertificate> idCert = keyChain.getCertificate(certName);
+ io::save(*idCert, "trust-anchor-5.cert");
+
+ Name dataName1 = identity;
+ dataName1.append("1");
+ shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity));
+
+ Name dataName2 = identity;
+ shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity));
+
+ Name dataName3("/TestValidatorConfig/KeyLocatorNameChecker1");
+ shared_ptr<Data> data3 = make_shared<Data>(dataName3);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data3, identity));
+
+ const std::string CONFIG =
+ "rule\n"
+ "{\n"
+ " id \"Simple3 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"
+ "trust-anchor\n"
+ "{\n"
+ " type file\n"
+ " file-name \"trust-anchor-5.cert\"\n"
+ "}\n";
+ const boost::filesystem::path CONFIG_PATH =
+ (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+ shared_ptr<Face> face = make_shared<Face>();
+ ValidatorConfig validator(face);
+ validator.load(CONFIG, CONFIG_PATH.native());
+
+ validator.validate(*data1,
+ bind(&onValidated, _1),
+ bind(&onValidationFailed, _1, _2));
+
+ validator.validate(*data2,
+ bind(&onIntentionalFailureValidated, _1),
+ bind(&onIntentionalFailureInvalidated, _1, _2));
+
+ validator.validate(*data3,
+ bind(&onIntentionalFailureValidated, _1),
+ bind(&onIntentionalFailureInvalidated, _1, _2));
+
+ keyChain.deleteIdentity(identity);
+
+ const boost::filesystem::path CERT_PATH =
+ (boost::filesystem::current_path() / std::string("trust-anchor-5.cert"));
+ boost::filesystem::remove(CERT_PATH);
+}
+
+struct FacesFixture
+{
+ FacesFixture()
+ : regPrefixId(0)
+ , regPrefixId2(0)
+ {}
+
+ void
+ onInterest(shared_ptr<Face> face, shared_ptr<Data> data)
+ {
+ face->put(*data);
+ face->unsetInterestFilter(regPrefixId);
+ }
+
+ void
+ onInterest2(shared_ptr<Face> face, shared_ptr<Data> data)
+ {
+ face->put(*data);
+ face->unsetInterestFilter(regPrefixId2);
+ }
+
+ void
+ onRegFailed()
+ {}
+
+ void
+ validate1(shared_ptr<ValidatorConfig> validator, shared_ptr<Data> data)
+ {
+ validator->validate(*data,
+ bind(&onValidated, _1),
+ bind(&onValidationFailed, _1, _2));
+ }
+
+ void
+ validate2(shared_ptr<ValidatorConfig> validator, shared_ptr<Data> data)
+ {
+ validator->validate(*data,
+ bind(&onIntentionalFailureValidated, _1),
+ bind(&onIntentionalFailureInvalidated, _1, _2));
+ }
+
+ void
+ validate3(shared_ptr<ValidatorConfig> validator, shared_ptr<Interest> interest)
+ {
+ validator->validate(*interest,
+ bind(&onValidated2, _1),
+ bind(&onValidationFailed2, _1, _2));
+ }
+
+ void
+ validate4(shared_ptr<ValidatorConfig> validator, shared_ptr<Interest> interest)
+ {
+ validator->validate(*interest,
+ bind(&onIntentionalFailureValidated2, _1),
+ bind(&onIntentionalFailureInvalidated2, _1, _2));
+ }
+
+ void
+ terminate(shared_ptr<Face> face)
+ {
+ face->ioService()->stop();
+ }
+
+ const RegisteredPrefixId* regPrefixId;
+ const RegisteredPrefixId* regPrefixId2;
+};
+
+BOOST_FIXTURE_TEST_CASE(HierarchicalChecker, FacesFixture)
+{
+ KeyChain keyChain;
+ std::vector<CertificateSubjectDescription> subjectDescription;
+
+ Name root("/TestValidatorConfig");
+ Name rootCertName = keyChain.createIdentity(root);
+ shared_ptr<IdentityCertificate> rootCert =
+ keyChain.getCertificate(rootCertName);
+ io::save(*rootCert, "trust-anchor-6.cert");
+
+
+ Name sld("/TestValidatorConfig/HierarchicalChecker");
+ Name sldKeyName = keyChain.generateRSAKeyPairAsDefault(sld, true);
+ shared_ptr<IdentityCertificate> sldCert =
+ keyChain.prepareUnsignedIdentityCertificate(sldKeyName,
+ root,
+ time::system_clock::now(),
+ time::system_clock::now() + time::days(7300),
+ subjectDescription);
+ keyChain.signByIdentity(*sldCert, root);
+ keyChain.addCertificateAsIdentityDefault(*sldCert);
+
+ Name nld("/TestValidatorConfig/HierarchicalChecker/NextLevel");
+ Name nldKeyName = keyChain.generateRSAKeyPairAsDefault(nld, true);
+ shared_ptr<IdentityCertificate> nldCert =
+ keyChain.prepareUnsignedIdentityCertificate(nldKeyName,
+ sld,
+ time::system_clock::now(),
+ time::system_clock::now() + time::days(7300),
+ subjectDescription);
+ keyChain.signByIdentity(*nldCert, sld);
+ keyChain.addCertificateAsIdentityDefault(*nldCert);
+
+ shared_ptr<Face> face = make_shared<Face>();
+ shared_ptr<Face> face2 = shared_ptr<Face>(new Face(face->ioService()));
+ Scheduler scheduler(*face->ioService());
+
+ scheduler.scheduleEvent(time::seconds(1),
+ bind(&FacesFixture::terminate, this, face));
+
+ regPrefixId = face->setInterestFilter(sldCert->getName().getPrefix(-1),
+ bind(&FacesFixture::onInterest, this, face, sldCert),
+ bind(&FacesFixture::onRegFailed, this));
+
+ regPrefixId2 = face->setInterestFilter(nldCert->getName().getPrefix(-1),
+ bind(&FacesFixture::onInterest2, this, face, nldCert),
+ bind(&FacesFixture::onRegFailed, this));
+
+ Name dataName1 = nld;
+ dataName1.append("data1");
+ shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, nld));
+
+ Name dataName2("/ConfValidatorTest");
+ dataName2.append("data1");
+ shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, nld));
+
+
+ const std::string CONFIG =
+ "rule\n"
+ "{\n"
+ " id \"Simple3 Rule\"\n"
+ " for data\n"
+ " checker\n"
+ " {\n"
+ " type hierarchical\n"
+ " sig-type rsa-sha256\n"
+ " }\n"
+ "}\n"
+ "trust-anchor\n"
+ "{\n"
+ " type file\n"
+ " file-name \"trust-anchor-6.cert\"\n"
+ "}\n";
+ const boost::filesystem::path CONFIG_PATH =
+ (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+ shared_ptr<ValidatorConfig> validator = shared_ptr<ValidatorConfig>(new ValidatorConfig(face2));
+ validator->load(CONFIG, CONFIG_PATH.native());
+
+ scheduler.scheduleEvent(time::milliseconds(200),
+ bind(&FacesFixture::validate1, this,
+ validator, data1));
+
+ scheduler.scheduleEvent(time::milliseconds(400),
+ bind(&FacesFixture::validate2, this,
+ validator, data2));
+
+ BOOST_REQUIRE_NO_THROW(face->processEvents());
+
+ keyChain.deleteIdentity(root);
+ keyChain.deleteIdentity(sld);
+ keyChain.deleteIdentity(nld);
+
+ const boost::filesystem::path CERT_PATH =
+ (boost::filesystem::current_path() / std::string("trust-anchor-6.cert"));
+ boost::filesystem::remove(CERT_PATH);
+}
+
+BOOST_AUTO_TEST_CASE(FixedSingerChecker)
+{
+ KeyChain keyChain;
+
+ Name identity("/TestValidatorConfig/FixedSingerChecker");
+
+ Name identity1 = identity;
+ identity1.append("1").appendVersion();
+ BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity1));
+ Name certName1 = keyChain.getDefaultCertificateNameForIdentity(identity1);
+ shared_ptr<IdentityCertificate> idCert1 = keyChain.getCertificate(certName1);
+ io::save(*idCert1, "trust-anchor-7.cert");
+
+ Name identity2 = identity;
+ identity2.append("2").appendVersion();
+ BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity2));
+
+ Name dataName1 = identity;
+ dataName1.append("data").appendVersion();
+ shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity1));
+
+ Name dataName2 = identity;
+ dataName2.append("data").appendVersion();
+ shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity2));
+
+ const std::string CONFIG =
+ "rule\n"
+ "{\n"
+ " id \"Simple3 Rule\"\n"
+ " for data\n"
+ " filter"
+ " {\n"
+ " type name\n"
+ " name /TestValidatorConfig/FixedSingerChecker\n"
+ " relation is-strict-prefix-of\n"
+ " }\n"
+ " checker\n"
+ " {\n"
+ " type fixed-signer\n"
+ " sig-type rsa-sha256\n"
+ " signer\n"
+ " {\n"
+ " type file\n"
+ " file-name \"trust-anchor-7.cert\"\n"
+ " }\n"
+ " }\n"
+ "}\n";
+ const boost::filesystem::path CONFIG_PATH =
+ (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+ shared_ptr<Face> face = make_shared<Face>();
+ ValidatorConfig validator(face);
+ validator.load(CONFIG, CONFIG_PATH.native());
+
+ validator.validate(*data1,
+ bind(&onValidated, _1),
+ bind(&onValidationFailed, _1, _2));
+
+ validator.validate(*data2,
+ bind(&onIntentionalFailureValidated, _1),
+ bind(&onIntentionalFailureInvalidated, _1, _2));
+
+
+ keyChain.deleteIdentity(identity1);
+ keyChain.deleteIdentity(identity2);
+
+ const boost::filesystem::path CERT_PATH =
+ (boost::filesystem::current_path() / std::string("trust-anchor-7.cert"));
+ boost::filesystem::remove(CERT_PATH);
+}
+
+
+BOOST_FIXTURE_TEST_CASE(Nrd, FacesFixture)
+{
+ KeyChain keyChain;
+ std::vector<CertificateSubjectDescription> subjectDescription;
+
+ Name root("/TestValidatorConfig");
+ Name rootCertName = keyChain.createIdentity(root);
+ shared_ptr<IdentityCertificate> rootCert =
+ keyChain.getCertificate(rootCertName);
+ io::save(*rootCert, "trust-anchor-8.cert");
+
+
+ Name sld("/TestValidatorConfig/Nrd-1");
+ Name sldKeyName = keyChain.generateRSAKeyPairAsDefault(sld, true);
+ shared_ptr<IdentityCertificate> sldCert =
+ keyChain.prepareUnsignedIdentityCertificate(sldKeyName,
+ root,
+ time::system_clock::now(),
+ time::system_clock::now() + time::days(7300),
+ subjectDescription);
+ keyChain.signByIdentity(*sldCert, root);
+ keyChain.addCertificateAsIdentityDefault(*sldCert);
+
+ Name nld("/TestValidatorConfig/Nrd-1/Nrd-2");
+ Name nldKeyName = keyChain.generateRSAKeyPairAsDefault(nld, true);
+ shared_ptr<IdentityCertificate> nldCert =
+ keyChain.prepareUnsignedIdentityCertificate(nldKeyName,
+ sld,
+ time::system_clock::now(),
+ time::system_clock::now() + time::days(7300),
+ subjectDescription);
+ keyChain.signByIdentity(*nldCert, sld);
+ keyChain.addCertificateAsIdentityDefault(*nldCert);
+
+ shared_ptr<Face> face = make_shared<Face>();
+ shared_ptr<Face> face2 = shared_ptr<Face>(new Face(face->ioService()));
+ Scheduler scheduler(*face->ioService());
+
+ scheduler.scheduleEvent(time::seconds(1),
+ bind(&FacesFixture::terminate, this, face));
+
+ regPrefixId = face->setInterestFilter(sldCert->getName().getPrefix(-1),
+ bind(&FacesFixture::onInterest, this, face, sldCert),
+ bind(&FacesFixture::onRegFailed, this));
+
+ regPrefixId2 = face->setInterestFilter(nldCert->getName().getPrefix(-1),
+ bind(&FacesFixture::onInterest2, this, face, nldCert),
+ bind(&FacesFixture::onRegFailed, this));
+
+ Name interestName1("/localhost/nrd/register/option/timestamp/nonce");
+ shared_ptr<Interest> interest1 = make_shared<Interest>(interestName1);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*interest1, nld));
+
+ Name interestName2("/localhost/nrd/non-register");
+ shared_ptr<Interest> interest2 = make_shared<Interest>(interestName2);
+ BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*interest2, nld));
+
+
+ const std::string CONFIG =
+ "rule\n"
+ "{\n"
+ " id \"NRD Prefix Registration Command Rule\"\n"
+ " for interest\n"
+ " filter\n"
+ " {\n"
+ " type name\n"
+ " regex ^<localhost><nrd>[<register><unregister><advertise><withdraw>]<>{3}$\n"
+ " }\n"
+ " checker\n"
+ " {\n"
+ " type customized\n"
+ " sig-type rsa-sha256\n"
+ " key-locator\n"
+ " {\n"
+ " type name\n"
+ " regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "rule\n"
+ "{\n"
+ " id \"Testbed Hierarchy Rule\"\n"
+ " for data\n"
+ " filter\n"
+ " {\n"
+ " type name\n"
+ " regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT><>$\n"
+ " }\n"
+ " checker\n"
+ " {\n"
+ " type hierarchical\n"
+ " sig-type rsa-sha256\n"
+ " }\n"
+ "}\n"
+ "trust-anchor\n"
+ "{\n"
+ " type file\n"
+ " file-name \"trust-anchor-8.cert\"\n"
+ "}\n";
+ const boost::filesystem::path CONFIG_PATH =
+ (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+ shared_ptr<ValidatorConfig> validator = shared_ptr<ValidatorConfig>(new ValidatorConfig(face2));
+ validator->load(CONFIG, CONFIG_PATH.native());
+
+ scheduler.scheduleEvent(time::milliseconds(200),
+ bind(&FacesFixture::validate3, this,
+ validator, interest1));
+
+ scheduler.scheduleEvent(time::milliseconds(400),
+ bind(&FacesFixture::validate4, this,
+ validator, interest2));
+
+ BOOST_REQUIRE_NO_THROW(face->processEvents());
+
+ keyChain.deleteIdentity(root);
+ keyChain.deleteIdentity(sld);
+ keyChain.deleteIdentity(nld);
+
+ const boost::filesystem::path CERT_PATH =
+ (boost::filesystem::current_path() / std::string("trust-anchor-8.cert"));
+ boost::filesystem::remove(CERT_PATH);
+}
+
+
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace ndn