blob: 7a9ff0b77e4fbfbe8e45dcdcfd070c28714585a4 [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_KEY_LOCATOR_CHECKER_HPP
25#define NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP
26
27#include "../../common.hpp"
28#include "../../data.hpp"
29#include "../../interest.hpp"
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070030#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
40class KeyLocatorCheckerFactory;
41
Yingdi Yu0f5fb692014-06-10 12:07:28 -070042/**
43 * @brief KeyLocatorChecker is one of the classes used by ValidatorConfig.
44 *
45 * The ValidatorConfig class consists of a set of rules.
46 * The KeyLocatorChecker class is part of a rule and is used to check if the KeyLocator field of a
47 * packet satisfy the requirements.
48 */
49
50
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070051class KeyLocatorChecker
52{
53public:
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070054 enum Relation {
55 RELATION_EQUAL,
56 RELATION_IS_PREFIX_OF,
57 RELATION_IS_STRICT_PREFIX_OF
58 };
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070059
60 virtual
61 ~KeyLocatorChecker()
62 {
63 }
64
65 bool
66 check(const Data& data,
67 const KeyLocator& keyLocator,
68 std::string& failInfo)
69 {
70 return check(data.getName(), keyLocator, failInfo);
71 }
72
73 bool
74 check(const Interest& interest,
75 const KeyLocator& keyLocator,
76 std::string& failInfo)
77 {
Yingdi Yu0f5fb692014-06-10 12:07:28 -070078 if (interest.getName().size() < signed_interest::MIN_LENGTH)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070079 {
80 failInfo = "No Signature";
81 return false;
82 }
83
Yingdi Yu0f5fb692014-06-10 12:07:28 -070084 Name signedName = interest.getName().getPrefix(-signed_interest::MIN_LENGTH);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070085 return check(signedName, keyLocator, failInfo);
86 }
87
88protected:
89
90 virtual bool
91 check(const Name& packetName,
92 const KeyLocator& keyLocator,
93 std::string& failInfo) = 0;
94
95 bool
96 checkRelation(const Relation& relation, const Name& name1, const Name& name2)
97 {
98 switch (relation)
99 {
100 case RELATION_EQUAL:
101 return (name1 == name2);
102 case RELATION_IS_PREFIX_OF:
103 return name1.isPrefixOf(name2);
104 case RELATION_IS_STRICT_PREFIX_OF:
105 return (name1.isPrefixOf(name2) && name1 != name2);
106 default:
107 return false;
108 }
109 }
110};
111
112class RelationKeyLocatorNameChecker : public KeyLocatorChecker
113{
114public:
115 RelationKeyLocatorNameChecker(const Name& name,
116 const KeyLocatorChecker::Relation& relation)
117 : m_name(name)
118 , m_relation(relation)
119 {
120 }
121
122protected:
123 virtual bool
124 check(const Name& packetName,
125 const KeyLocator& keyLocator,
126 std::string& failInfo)
127 {
128 try
129 {
130 if (checkRelation(m_relation, m_name, keyLocator.getName()))
131 return true;
132
133 failInfo = "KeyLocatorChecker failed!";
134 return false;
135 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700136 catch (KeyLocator::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700137 {
138 failInfo = "KeyLocator does not have name";
139 return false;
140 }
141 }
142
143private:
144 Name m_name;
145 KeyLocatorChecker::Relation m_relation;
146};
147
148class RegexKeyLocatorNameChecker : public KeyLocatorChecker
149{
150public:
Alexander Afanasyeva4297a62014-06-19 13:29:34 -0700151 explicit
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700152 RegexKeyLocatorNameChecker(const Regex& regex)
153 : m_regex(regex)
154 {
155 }
156
157protected:
158 virtual bool
159 check(const Name& packetName,
160 const KeyLocator& keyLocator,
161 std::string& failInfo)
162 {
163 try
164 {
165 if (m_regex.match(keyLocator.getName()))
166 return true;
167
168 failInfo = "KeyLocatorChecker failed!";
169 return false;
170 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700171 catch (KeyLocator::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700172 {
173 failInfo = "KeyLocator does not have name";
174 return false;
175 }
176 }
177
178private:
179 Regex m_regex;
180};
181
182class HyperKeyLocatorNameChecker : public KeyLocatorChecker
183{
184public:
185 HyperKeyLocatorNameChecker(const std::string& pExpr, const std::string pExpand,
186 const std::string& kExpr, const std::string kExpand,
187 const Relation& hyperRelation)
188 : m_hyperPRegex(new Regex(pExpr, pExpand))
189 , m_hyperKRegex(new Regex(kExpr, kExpand))
190 , m_hyperRelation(hyperRelation)
191 {
192 }
193
194protected:
195 virtual bool
196 check(const Name& packetName,
197 const KeyLocator& keyLocator,
198 std::string& failInfo)
199 {
200 try
201 {
202 if (m_hyperPRegex->match(packetName) &&
203 m_hyperKRegex->match(keyLocator.getName()) &&
204 checkRelation(m_hyperRelation,
205 m_hyperKRegex->expand(),
206 m_hyperPRegex->expand()))
207 return true;
208
209 failInfo = "KeyLocatorChecker failed!";
210 return false;
211 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700212 catch (KeyLocator::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700213 {
214 failInfo = "KeyLocator does not have name";
215 return false;
216 }
217
218 }
219
220private:
221 shared_ptr<Regex> m_hyperPRegex;
222 shared_ptr<Regex> m_hyperKRegex;
223 Relation m_hyperRelation;
224};
225
226
227class KeyLocatorCheckerFactory
228{
229public:
230 static shared_ptr<KeyLocatorChecker>
231 create(const ConfigSection& configSection, const std::string& filename)
232 {
233 ConfigSection::const_iterator propertyIt = configSection.begin();
234
235 // Get checker.key-locator.type
236 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700237 BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.type>!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700238
239 std::string type = propertyIt->second.data();
240
241 if (boost::iequals(type, "name"))
242 return createKeyLocatorNameChecker(configSection, filename);
243 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700244 BOOST_THROW_EXCEPTION(Error("Unsupported checker.key-locator.type: " + type));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700245 }
246
247private:
248 static shared_ptr<KeyLocatorChecker>
249 createKeyLocatorNameChecker(const ConfigSection& configSection,
250 const std::string& filename)
251 {
252 ConfigSection::const_iterator propertyIt = configSection.begin();
253 propertyIt++;
254
255 if (propertyIt == configSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700256 BOOST_THROW_EXCEPTION(Error("Expect more checker.key-locator properties"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700257
258 if (boost::iequals(propertyIt->first, "name"))
259 {
260 Name name;
261 try
262 {
263 name = Name(propertyIt->second.data());
264 }
265 catch (Name::Error& e)
266 {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700267 BOOST_THROW_EXCEPTION(Error("Invalid checker.key-locator.name: " +
268 propertyIt->second.data()));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700269 }
270 propertyIt++;
271
272 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700273 BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.relation>!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700274
275 std::string relationString = propertyIt->second.data();
276 propertyIt++;
277
278 KeyLocatorChecker::Relation relation;
279 if (boost::iequals(relationString, "equal"))
280 relation = KeyLocatorChecker::RELATION_EQUAL;
281 else if (boost::iequals(relationString, "is-prefix-of"))
282 relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
283 else if (boost::iequals(relationString, "is-strict-prefix-of"))
284 relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
285 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700286 BOOST_THROW_EXCEPTION(Error("Unsupported relation: " + relationString));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700287
288 if (propertyIt != configSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700289 BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700290
291 return shared_ptr<RelationKeyLocatorNameChecker>
292 (new RelationKeyLocatorNameChecker(name, relation));
293 }
294 else if (boost::iequals(propertyIt->first, "regex"))
295 {
296 std::string regexString = propertyIt->second.data();
297 propertyIt++;
298
299 if (propertyIt != configSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700300 BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700301
302 try
303 {
304 return shared_ptr<RegexKeyLocatorNameChecker>
305 (new RegexKeyLocatorNameChecker(regexString));
306 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700307 catch (Regex::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700308 {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700309 BOOST_THROW_EXCEPTION(Error("Invalid checker.key-locator.regex: " + regexString));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700310 }
311 }
312 else if (boost::iequals(propertyIt->first, "hyper-relation"))
313 {
314 const ConfigSection& hSection = propertyIt->second;
315
316 ConfigSection::const_iterator hPropertyIt = hSection.begin();
317
318 // Get k-regex
319 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-regex"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700320 BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.k-regex>!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700321
322 std::string kRegex = hPropertyIt->second.data();
323 hPropertyIt++;
324
325 // Get k-expand
326 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-expand"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700327 BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.k-expand>!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700328
329 std::string kExpand = hPropertyIt->second.data();
330 hPropertyIt++;
331
332 // Get h-relation
333 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "h-relation"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700334 BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.h-relation>!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700335
336 std::string hRelation = hPropertyIt->second.data();
337 hPropertyIt++;
338
339 // Get p-regex
340 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-regex"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700341 BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.p-regex>!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700342
343 std::string pRegex = hPropertyIt->second.data();
344 hPropertyIt++;
345
346 // Get p-expand
347 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-expand"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700348 BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.p-expand>!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700349
350 std::string pExpand = hPropertyIt->second.data();
351 hPropertyIt++;
352
353 if (hPropertyIt != hSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700354 BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator.hyper-relation!"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700355
356 KeyLocatorChecker::Relation relation;
357 if (boost::iequals(hRelation, "equal"))
358 relation = KeyLocatorChecker::RELATION_EQUAL;
359 else if (boost::iequals(hRelation, "is-prefix-of"))
360 relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
361 else if (boost::iequals(hRelation, "is-strict-prefix-of"))
362 relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
363 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700364 BOOST_THROW_EXCEPTION(Error("Unsupported checker.key-locator.hyper-relation.h-relation: "
365 + hRelation));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700366
367 try
368 {
369 return shared_ptr<HyperKeyLocatorNameChecker>
370 (new HyperKeyLocatorNameChecker(pRegex, pExpand,
371 kRegex, kExpand,
372 relation));
373 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700374 catch (Regex::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700375 {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700376 BOOST_THROW_EXCEPTION(Error("Invalid regex for key-locator.hyper-relation"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700377 }
378 }
379 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700380 BOOST_THROW_EXCEPTION(Error("Unsupported checker.key-locator"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700381 }
382};
383
384
385} // namespace conf
386} // namespace security
387} // namespace ndn
388
389#endif // NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP