blob: fb2c15d0f1af66507fb55e66b5a760ca668a50ae [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 Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 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"
31#include <boost/algorithm/string.hpp>
32
33#include "common.hpp"
34
35namespace ndn {
36namespace security {
37namespace conf {
38
39class Filter
40{
41public:
42 virtual
43 ~Filter()
44 {
45 }
46
47 virtual bool
48 match(const Data& data) = 0;
49
50 virtual bool
51 match(const Interest& interest) = 0;
52};
53
54class RelationNameFilter : public Filter
55{
56public:
57 enum Relation
58 {
59 RELATION_EQUAL,
60 RELATION_IS_PREFIX_OF,
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070061 RELATION_IS_STRICT_PREFIX_OF
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070062 };
63
64 RelationNameFilter(const Name& name, Relation relation)
65 : m_name(name)
66 , m_relation(relation)
67 {
68 }
69
70 virtual
71 ~RelationNameFilter()
72 {
73 }
74
75 virtual bool
76 match(const Data& data)
77 {
78 return match(data.getName());
79 }
80
81 virtual bool
82 match(const Interest& interest)
83 {
84 if (interest.getName().size() < 2)
85 return false;
86
87 Name signedName = interest.getName().getPrefix(-2);
88 return match(signedName);
89 }
90
91private:
92 bool
93 match(const Name& name)
94 {
95 switch (m_relation)
96 {
97 case RELATION_EQUAL:
98 return (name == m_name);
99 case RELATION_IS_PREFIX_OF:
100 return m_name.isPrefixOf(name);
101 case RELATION_IS_STRICT_PREFIX_OF:
102 return (m_name.isPrefixOf(name) && m_name != name);
103 default:
104 return false;
105 }
106 }
107
108private:
109 Name m_name;
110 Relation m_relation;
111};
112
113class RegexNameFilter : public Filter
114{
115public:
116 explicit
117 RegexNameFilter(const Regex& regex)
118 : m_regex(regex)
119 {
120 }
121
122 virtual
123 ~RegexNameFilter()
124 {
125 }
126
127 virtual bool
128 match(const Data& data)
129 {
130 return m_regex.match(data.getName());
131 }
132
133 virtual bool
134 match(const Interest& interest)
135 {
136 if (interest.getName().size() < 2)
137 return false;
138
139 Name signedName = interest.getName().getPrefix(-2);
140 return m_regex.match(signedName);
141 }
142
143private:
144 Regex m_regex;
145};
146
147class FilterFactory
148{
149public:
150 static shared_ptr<Filter>
151 create(const ConfigSection& configSection)
152 {
153 ConfigSection::const_iterator propertyIt = configSection.begin();
154
155 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
156 throw Error("Expect <filter.type>!");
157
158 std::string type = propertyIt->second.data();
159
160 if (boost::iequals(type, "name"))
161 return createNameFilter(configSection);
162 else
163 throw Error("Unsupported filter.type: " + type);
164 }
165private:
166 static shared_ptr<Filter>
167 createNameFilter(const ConfigSection& configSection)
168 {
169 ConfigSection::const_iterator propertyIt = configSection.begin();
170 propertyIt++;
171
172 if (propertyIt == configSection.end())
173 throw Error("Expect more properties for filter(name)");
174
175 if (boost::iequals(propertyIt->first, "name"))
176 {
177 // Get filter.name
178 Name name;
179 try
180 {
181 name = Name(propertyIt->second.data());
182 }
183 catch (Name::Error& e)
184 {
185 throw Error("Wrong filter.name: " + propertyIt->second.data());
186 }
187
188 propertyIt++;
189
190 // Get filter.relation
191 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
192 throw Error("Expect <filter.relation>!");
193
194 std::string relationString = propertyIt->second.data();
195 propertyIt++;
196
197 RelationNameFilter::Relation relation;
198 if (boost::iequals(relationString, "equal"))
199 relation = RelationNameFilter::RELATION_EQUAL;
200 else if (boost::iequals(relationString, "is-prefix-of"))
201 relation = RelationNameFilter::RELATION_IS_PREFIX_OF;
202 else if (boost::iequals(relationString, "is-strict-prefix-of"))
203 relation = RelationNameFilter::RELATION_IS_STRICT_PREFIX_OF;
204 else
205 throw Error("Unsupported relation: " + relationString);
206
207
208 if (propertyIt != configSection.end())
209 throw Error("Expect the end of filter!");
210
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700211 return make_shared<RelationNameFilter>(name, relation);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700212 }
213 else if (boost::iequals(propertyIt->first, "regex"))
214 {
215 std::string regexString = propertyIt->second.data();
216 propertyIt++;
217
218 if (propertyIt != configSection.end())
219 throw Error("Expect the end of filter!");
220
221 try
222 {
223 return shared_ptr<RegexNameFilter>(new RegexNameFilter(regexString));
224 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700225 catch (Regex::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700226 {
227 throw Error("Wrong filter.regex: " + regexString);
228 }
229 }
230 else
231 throw Error("Wrong filter(name) properties");
232 }
233};
234
235} // namespace conf
236} // namespace security
237} // namespace ndn
238
239#endif // NDN_SECURITY_CONF_FILTER_HPP