blob: 5891c766fd9a7d9504ec3094254b1e72186aaaec [file] [log] [blame]
Yingdi Yu48e8c0c2014-03-19 12:01:55 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070013 */
14
15#ifndef NDN_SECURITY_CONF_FILTER_HPP
16#define NDN_SECURITY_CONF_FILTER_HPP
17
18#include "../../common.hpp"
19#include "../../data.hpp"
20#include "../../interest.hpp"
21#include "../../util/regex.hpp"
22#include <boost/algorithm/string.hpp>
23
24#include "common.hpp"
25
26namespace ndn {
27namespace security {
28namespace conf {
29
30class Filter
31{
32public:
33 virtual
34 ~Filter()
35 {
36 }
37
38 virtual bool
39 match(const Data& data) = 0;
40
41 virtual bool
42 match(const Interest& interest) = 0;
43};
44
45class RelationNameFilter : public Filter
46{
47public:
48 enum Relation
49 {
50 RELATION_EQUAL,
51 RELATION_IS_PREFIX_OF,
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070052 RELATION_IS_STRICT_PREFIX_OF
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070053 };
54
55 RelationNameFilter(const Name& name, Relation relation)
56 : m_name(name)
57 , m_relation(relation)
58 {
59 }
60
61 virtual
62 ~RelationNameFilter()
63 {
64 }
65
66 virtual bool
67 match(const Data& data)
68 {
69 return match(data.getName());
70 }
71
72 virtual bool
73 match(const Interest& interest)
74 {
75 if (interest.getName().size() < 2)
76 return false;
77
78 Name signedName = interest.getName().getPrefix(-2);
79 return match(signedName);
80 }
81
82private:
83 bool
84 match(const Name& name)
85 {
86 switch (m_relation)
87 {
88 case RELATION_EQUAL:
89 return (name == m_name);
90 case RELATION_IS_PREFIX_OF:
91 return m_name.isPrefixOf(name);
92 case RELATION_IS_STRICT_PREFIX_OF:
93 return (m_name.isPrefixOf(name) && m_name != name);
94 default:
95 return false;
96 }
97 }
98
99private:
100 Name m_name;
101 Relation m_relation;
102};
103
104class RegexNameFilter : public Filter
105{
106public:
107 explicit
108 RegexNameFilter(const Regex& regex)
109 : m_regex(regex)
110 {
111 }
112
113 virtual
114 ~RegexNameFilter()
115 {
116 }
117
118 virtual bool
119 match(const Data& data)
120 {
121 return m_regex.match(data.getName());
122 }
123
124 virtual bool
125 match(const Interest& interest)
126 {
127 if (interest.getName().size() < 2)
128 return false;
129
130 Name signedName = interest.getName().getPrefix(-2);
131 return m_regex.match(signedName);
132 }
133
134private:
135 Regex m_regex;
136};
137
138class FilterFactory
139{
140public:
141 static shared_ptr<Filter>
142 create(const ConfigSection& configSection)
143 {
144 ConfigSection::const_iterator propertyIt = configSection.begin();
145
146 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
147 throw Error("Expect <filter.type>!");
148
149 std::string type = propertyIt->second.data();
150
151 if (boost::iequals(type, "name"))
152 return createNameFilter(configSection);
153 else
154 throw Error("Unsupported filter.type: " + type);
155 }
156private:
157 static shared_ptr<Filter>
158 createNameFilter(const ConfigSection& configSection)
159 {
160 ConfigSection::const_iterator propertyIt = configSection.begin();
161 propertyIt++;
162
163 if (propertyIt == configSection.end())
164 throw Error("Expect more properties for filter(name)");
165
166 if (boost::iequals(propertyIt->first, "name"))
167 {
168 // Get filter.name
169 Name name;
170 try
171 {
172 name = Name(propertyIt->second.data());
173 }
174 catch (Name::Error& e)
175 {
176 throw Error("Wrong filter.name: " + propertyIt->second.data());
177 }
178
179 propertyIt++;
180
181 // Get filter.relation
182 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
183 throw Error("Expect <filter.relation>!");
184
185 std::string relationString = propertyIt->second.data();
186 propertyIt++;
187
188 RelationNameFilter::Relation relation;
189 if (boost::iequals(relationString, "equal"))
190 relation = RelationNameFilter::RELATION_EQUAL;
191 else if (boost::iequals(relationString, "is-prefix-of"))
192 relation = RelationNameFilter::RELATION_IS_PREFIX_OF;
193 else if (boost::iequals(relationString, "is-strict-prefix-of"))
194 relation = RelationNameFilter::RELATION_IS_STRICT_PREFIX_OF;
195 else
196 throw Error("Unsupported relation: " + relationString);
197
198
199 if (propertyIt != configSection.end())
200 throw Error("Expect the end of filter!");
201
202 return make_shared<RelationNameFilter>(boost::cref(name),
203 boost::cref(relation));
204 }
205 else if (boost::iequals(propertyIt->first, "regex"))
206 {
207 std::string regexString = propertyIt->second.data();
208 propertyIt++;
209
210 if (propertyIt != configSection.end())
211 throw Error("Expect the end of filter!");
212
213 try
214 {
215 return shared_ptr<RegexNameFilter>(new RegexNameFilter(regexString));
216 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700217 catch (Regex::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700218 {
219 throw Error("Wrong filter.regex: " + regexString);
220 }
221 }
222 else
223 throw Error("Wrong filter(name) properties");
224 }
225};
226
227} // namespace conf
228} // namespace security
229} // namespace ndn
230
231#endif // NDN_SECURITY_CONF_FILTER_HPP