blob: 52cf888e2c866352c5d8e1e550847aed65a0e4e5 [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_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 Yu0f5fb692014-06-10 12:07:28 -070030#include "../security-common.hpp"
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070031#include <boost/algorithm/string.hpp>
32
33#include "common.hpp"
34
35namespace ndn {
36namespace security {
37namespace conf {
38
39class KeyLocatorCheckerFactory;
40
Yingdi Yu0f5fb692014-06-10 12:07:28 -070041/**
42 * @brief KeyLocatorChecker is one of the classes used by ValidatorConfig.
43 *
44 * The ValidatorConfig class consists of a set of rules.
45 * The KeyLocatorChecker class is part of a rule and is used to check if the KeyLocator field of a
46 * packet satisfy the requirements.
47 */
48
49
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070050class KeyLocatorChecker
51{
52public:
53 enum Relation
54 {
55 RELATION_EQUAL,
56 RELATION_IS_PREFIX_OF,
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070057 RELATION_IS_STRICT_PREFIX_OF
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070058 };
59
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:
151 RegexKeyLocatorNameChecker(const Regex& regex)
152 : m_regex(regex)
153 {
154 }
155
156protected:
157 virtual bool
158 check(const Name& packetName,
159 const KeyLocator& keyLocator,
160 std::string& failInfo)
161 {
162 try
163 {
164 if (m_regex.match(keyLocator.getName()))
165 return true;
166
167 failInfo = "KeyLocatorChecker failed!";
168 return false;
169 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700170 catch (KeyLocator::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700171 {
172 failInfo = "KeyLocator does not have name";
173 return false;
174 }
175 }
176
177private:
178 Regex m_regex;
179};
180
181class HyperKeyLocatorNameChecker : public KeyLocatorChecker
182{
183public:
184 HyperKeyLocatorNameChecker(const std::string& pExpr, const std::string pExpand,
185 const std::string& kExpr, const std::string kExpand,
186 const Relation& hyperRelation)
187 : m_hyperPRegex(new Regex(pExpr, pExpand))
188 , m_hyperKRegex(new Regex(kExpr, kExpand))
189 , m_hyperRelation(hyperRelation)
190 {
191 }
192
193protected:
194 virtual bool
195 check(const Name& packetName,
196 const KeyLocator& keyLocator,
197 std::string& failInfo)
198 {
199 try
200 {
201 if (m_hyperPRegex->match(packetName) &&
202 m_hyperKRegex->match(keyLocator.getName()) &&
203 checkRelation(m_hyperRelation,
204 m_hyperKRegex->expand(),
205 m_hyperPRegex->expand()))
206 return true;
207
208 failInfo = "KeyLocatorChecker failed!";
209 return false;
210 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700211 catch (KeyLocator::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700212 {
213 failInfo = "KeyLocator does not have name";
214 return false;
215 }
216
217 }
218
219private:
220 shared_ptr<Regex> m_hyperPRegex;
221 shared_ptr<Regex> m_hyperKRegex;
222 Relation m_hyperRelation;
223};
224
225
226class KeyLocatorCheckerFactory
227{
228public:
229 static shared_ptr<KeyLocatorChecker>
230 create(const ConfigSection& configSection, const std::string& filename)
231 {
232 ConfigSection::const_iterator propertyIt = configSection.begin();
233
234 // Get checker.key-locator.type
235 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
236 throw Error("Expect <checker.key-locator.type>!");
237
238 std::string type = propertyIt->second.data();
239
240 if (boost::iequals(type, "name"))
241 return createKeyLocatorNameChecker(configSection, filename);
242 else
243 throw Error("Unsupported checker.key-locator.type: " + type);
244 }
245
246private:
247 static shared_ptr<KeyLocatorChecker>
248 createKeyLocatorNameChecker(const ConfigSection& configSection,
249 const std::string& filename)
250 {
251 ConfigSection::const_iterator propertyIt = configSection.begin();
252 propertyIt++;
253
254 if (propertyIt == configSection.end())
255 throw Error("Expect more checker.key-locator properties");
256
257 if (boost::iequals(propertyIt->first, "name"))
258 {
259 Name name;
260 try
261 {
262 name = Name(propertyIt->second.data());
263 }
264 catch (Name::Error& e)
265 {
266 throw Error("Invalid checker.key-locator.name: "
267 + propertyIt->second.data());
268 }
269 propertyIt++;
270
271 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
272 throw Error("Expect <checker.key-locator.relation>!");
273
274 std::string relationString = propertyIt->second.data();
275 propertyIt++;
276
277 KeyLocatorChecker::Relation relation;
278 if (boost::iequals(relationString, "equal"))
279 relation = KeyLocatorChecker::RELATION_EQUAL;
280 else if (boost::iequals(relationString, "is-prefix-of"))
281 relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
282 else if (boost::iequals(relationString, "is-strict-prefix-of"))
283 relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
284 else
285 throw Error("Unsupported relation: " + relationString);
286
287 if (propertyIt != configSection.end())
288 throw Error("Expect the end of checker.key-locator!");
289
290 return shared_ptr<RelationKeyLocatorNameChecker>
291 (new RelationKeyLocatorNameChecker(name, relation));
292 }
293 else if (boost::iequals(propertyIt->first, "regex"))
294 {
295 std::string regexString = propertyIt->second.data();
296 propertyIt++;
297
298 if (propertyIt != configSection.end())
299 throw Error("Expect the end of checker.key-locator!");
300
301 try
302 {
303 return shared_ptr<RegexKeyLocatorNameChecker>
304 (new RegexKeyLocatorNameChecker(regexString));
305 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700306 catch (Regex::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700307 {
308 throw Error("Invalid checker.key-locator.regex: " + regexString);
309 }
310 }
311 else if (boost::iequals(propertyIt->first, "hyper-relation"))
312 {
313 const ConfigSection& hSection = propertyIt->second;
314
315 ConfigSection::const_iterator hPropertyIt = hSection.begin();
316
317 // Get k-regex
318 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-regex"))
319 throw Error("Expect <checker.key-locator.hyper-relation.k-regex>!");
320
321 std::string kRegex = hPropertyIt->second.data();
322 hPropertyIt++;
323
324 // Get k-expand
325 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-expand"))
326 throw Error("Expect <checker.key-locator.hyper-relation.k-expand>!");
327
328 std::string kExpand = hPropertyIt->second.data();
329 hPropertyIt++;
330
331 // Get h-relation
332 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "h-relation"))
333 throw Error("Expect <checker.key-locator.hyper-relation.h-relation>!");
334
335 std::string hRelation = hPropertyIt->second.data();
336 hPropertyIt++;
337
338 // Get p-regex
339 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-regex"))
340 throw Error("Expect <checker.key-locator.hyper-relation.p-regex>!");
341
342 std::string pRegex = hPropertyIt->second.data();
343 hPropertyIt++;
344
345 // Get p-expand
346 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-expand"))
347 throw Error("Expect <checker.key-locator.hyper-relation.p-expand>!");
348
349 std::string pExpand = hPropertyIt->second.data();
350 hPropertyIt++;
351
352 if (hPropertyIt != hSection.end())
353 throw Error("Expect the end of checker.key-locator.hyper-relation!");
354
355 KeyLocatorChecker::Relation relation;
356 if (boost::iequals(hRelation, "equal"))
357 relation = KeyLocatorChecker::RELATION_EQUAL;
358 else if (boost::iequals(hRelation, "is-prefix-of"))
359 relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
360 else if (boost::iequals(hRelation, "is-strict-prefix-of"))
361 relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
362 else
363 throw Error("Unsupported checker.key-locator.hyper-relation.h-relation: "
364 + hRelation);
365
366 try
367 {
368 return shared_ptr<HyperKeyLocatorNameChecker>
369 (new HyperKeyLocatorNameChecker(pRegex, pExpand,
370 kRegex, kExpand,
371 relation));
372 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700373 catch (Regex::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700374 {
375 throw Error("Invalid regex for key-locator.hyper-relation");
376 }
377 }
378 else
379 throw Error("Unsupported checker.key-locator");
380 }
381};
382
383
384} // namespace conf
385} // namespace security
386} // namespace ndn
387
388#endif // NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP