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