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/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