blob: d191b1bb8bb21aeb65150417e794adbdca28a08d [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yu48e8c0c2014-03-19 12:01:55 -07002/**
Alexander Afanasyev73e30042015-09-17 17:09:51 -07003 * Copyright (c) 2013-2015 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070022 */
23
24#ifndef NDN_SECURITY_CONF_FILTER_HPP
25#define NDN_SECURITY_CONF_FILTER_HPP
26
27#include "../../common.hpp"
28#include "../../data.hpp"
29#include "../../interest.hpp"
30#include "../../util/regex.hpp"
Yingdi Yu0f5fb692014-06-10 12:07:28 -070031#include "../security-common.hpp"
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070032#include <boost/algorithm/string.hpp>
33
34#include "common.hpp"
35
36namespace ndn {
37namespace security {
38namespace conf {
39
Yingdi Yu0f5fb692014-06-10 12:07:28 -070040/**
41 * @brief Filter is one of the classes used by ValidatorConfig.
42 *
43 * The ValidatorConfig class consists of a set of rules.
44 * The Filter class is a part of a rule and is used to match packet.
45 * Matched packets will be checked against the checkers defined in the rule.
46 */
47
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070048class Filter
49{
50public:
Yingdi Yu0f5fb692014-06-10 12:07:28 -070051
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070052 virtual
53 ~Filter()
54 {
55 }
56
Yingdi Yu0f5fb692014-06-10 12:07:28 -070057 bool
58 match(const Data& data)
59 {
60 return matchName(data.getName());
61 }
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070062
Yingdi Yu0f5fb692014-06-10 12:07:28 -070063 bool
64 match(const Interest& interest)
65 {
66 if (interest.getName().size() < signed_interest::MIN_LENGTH)
67 return false;
68
69 Name unsignedName = interest.getName().getPrefix(-signed_interest::MIN_LENGTH);
70 return matchName(unsignedName);
71 }
72
73protected:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070074 virtual bool
Yingdi Yu0f5fb692014-06-10 12:07:28 -070075 matchName(const Name& name) = 0;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070076};
77
78class RelationNameFilter : public Filter
79{
80public:
81 enum Relation
82 {
83 RELATION_EQUAL,
84 RELATION_IS_PREFIX_OF,
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070085 RELATION_IS_STRICT_PREFIX_OF
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070086 };
87
88 RelationNameFilter(const Name& name, Relation relation)
89 : m_name(name)
90 , m_relation(relation)
91 {
92 }
93
94 virtual
95 ~RelationNameFilter()
96 {
97 }
98
Yingdi Yu0f5fb692014-06-10 12:07:28 -070099protected:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700100 virtual bool
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700101 matchName(const Name& name)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700102 {
103 switch (m_relation)
104 {
105 case RELATION_EQUAL:
106 return (name == m_name);
107 case RELATION_IS_PREFIX_OF:
108 return m_name.isPrefixOf(name);
109 case RELATION_IS_STRICT_PREFIX_OF:
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700110 return (m_name.isPrefixOf(name) && m_name.size() < name.size());
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700111 default:
112 return false;
113 }
114 }
115
116private:
117 Name m_name;
118 Relation m_relation;
119};
120
121class RegexNameFilter : public Filter
122{
123public:
124 explicit
125 RegexNameFilter(const Regex& regex)
126 : m_regex(regex)
127 {
128 }
129
130 virtual
131 ~RegexNameFilter()
132 {
133 }
134
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700135protected:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700136 virtual bool
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700137 matchName(const Name& name)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700138 {
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700139 return m_regex.match(name);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700140 }
141
142private:
143 Regex m_regex;
144};
145
146class FilterFactory
147{
148public:
149 static shared_ptr<Filter>
150 create(const ConfigSection& configSection)
151 {
152 ConfigSection::const_iterator propertyIt = configSection.begin();
153
154 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700155 BOOST_THROW_EXCEPTION(Error("Expect <filter.type>!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700156
157 std::string type = propertyIt->second.data();
158
159 if (boost::iequals(type, "name"))
160 return createNameFilter(configSection);
161 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700162 BOOST_THROW_EXCEPTION(Error("Unsupported filter.type: " + type));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700163 }
164private:
165 static shared_ptr<Filter>
166 createNameFilter(const ConfigSection& configSection)
167 {
168 ConfigSection::const_iterator propertyIt = configSection.begin();
169 propertyIt++;
170
171 if (propertyIt == configSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700172 BOOST_THROW_EXCEPTION(Error("Expect more properties for filter(name)"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700173
174 if (boost::iequals(propertyIt->first, "name"))
175 {
176 // Get filter.name
177 Name name;
178 try
179 {
180 name = Name(propertyIt->second.data());
181 }
182 catch (Name::Error& e)
183 {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700184 BOOST_THROW_EXCEPTION(Error("Wrong filter.name: " + propertyIt->second.data()));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700185 }
186
187 propertyIt++;
188
189 // Get filter.relation
190 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700191 BOOST_THROW_EXCEPTION(Error("Expect <filter.relation>!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700192
193 std::string relationString = propertyIt->second.data();
194 propertyIt++;
195
196 RelationNameFilter::Relation relation;
197 if (boost::iequals(relationString, "equal"))
198 relation = RelationNameFilter::RELATION_EQUAL;
199 else if (boost::iequals(relationString, "is-prefix-of"))
200 relation = RelationNameFilter::RELATION_IS_PREFIX_OF;
201 else if (boost::iequals(relationString, "is-strict-prefix-of"))
202 relation = RelationNameFilter::RELATION_IS_STRICT_PREFIX_OF;
203 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700204 BOOST_THROW_EXCEPTION(Error("Unsupported relation: " + relationString));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700205
206
207 if (propertyIt != configSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700208 BOOST_THROW_EXCEPTION(Error("Expect the end of filter!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700209
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700210 return make_shared<RelationNameFilter>(name, relation);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700211 }
212 else if (boost::iequals(propertyIt->first, "regex"))
213 {
214 std::string regexString = propertyIt->second.data();
215 propertyIt++;
216
217 if (propertyIt != configSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700218 BOOST_THROW_EXCEPTION(Error("Expect the end of filter!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700219
220 try
221 {
222 return shared_ptr<RegexNameFilter>(new RegexNameFilter(regexString));
223 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700224 catch (Regex::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700225 {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700226 BOOST_THROW_EXCEPTION(Error("Wrong filter.regex: " + regexString));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700227 }
228 }
229 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700230 BOOST_THROW_EXCEPTION(Error("Wrong filter(name) properties"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700231 }
232};
233
234} // namespace conf
235} // namespace security
236} // namespace ndn
237
238#endif // NDN_SECURITY_CONF_FILTER_HPP