| /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| /** |
| * Copyright (c) 2013-2014 Regents of the University of California. |
| * |
| * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). |
| * |
| * ndn-cxx library is free software: you can redistribute it and/or modify it under the |
| * terms of the GNU Lesser General Public License as published by the Free Software |
| * Foundation, either version 3 of the License, or (at your option) any later version. |
| * |
| * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY |
| * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
| * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
| * |
| * You should have received copies of the GNU General Public License and GNU Lesser |
| * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see |
| * <http://www.gnu.org/licenses/>. |
| * |
| * See AUTHORS.md for complete list of ndn-cxx authors and contributors. |
| * |
| * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/> |
| */ |
| |
| #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 "../security-common.hpp" |
| #include <boost/algorithm/string.hpp> |
| |
| #include "common.hpp" |
| |
| namespace ndn { |
| namespace security { |
| namespace conf { |
| |
| class KeyLocatorCheckerFactory; |
| |
| /** |
| * @brief KeyLocatorChecker is one of the classes used by ValidatorConfig. |
| * |
| * The ValidatorConfig class consists of a set of rules. |
| * The KeyLocatorChecker class is part of a rule and is used to check if the KeyLocator field of a |
| * packet satisfy the requirements. |
| */ |
| |
| |
| class KeyLocatorChecker |
| { |
| public: |
| enum Relation |
| { |
| RELATION_EQUAL, |
| RELATION_IS_PREFIX_OF, |
| RELATION_IS_STRICT_PREFIX_OF |
| }; |
| |
| virtual |
| ~KeyLocatorChecker() |
| { |
| } |
| |
| bool |
| check(const Data& data, |
| const KeyLocator& keyLocator, |
| std::string& failInfo) |
| { |
| return check(data.getName(), keyLocator, failInfo); |
| } |
| |
| bool |
| check(const Interest& interest, |
| const KeyLocator& keyLocator, |
| std::string& failInfo) |
| { |
| if (interest.getName().size() < signed_interest::MIN_LENGTH) |
| { |
| failInfo = "No Signature"; |
| return false; |
| } |
| |
| Name signedName = interest.getName().getPrefix(-signed_interest::MIN_LENGTH); |
| 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 (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 (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 (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 (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 (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 |