blob: 7d5bb9c036f986717a72097eddaa136bedd1b024 [file] [log] [blame]
/* -*- 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 "../../util/regex.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:
explicit
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